1 /* 2 * Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de> 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <dirent.h> 8 #include <errno.h> 9 #include <getopt.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 14 #include <Entry.h> 15 #include <Path.h> 16 17 #include <package/hpkg/HPKGDefs.h> 18 #include <package/hpkg/RepositoryWriter.h> 19 #include <package/PackageInfo.h> 20 #include <package/RepositoryInfo.h> 21 22 #include "package_repo.h" 23 24 25 using BPackageKit::BHPKG::BRepositoryWriterListener; 26 using BPackageKit::BHPKG::BRepositoryWriter; 27 using namespace BPackageKit; 28 29 30 class RepositoryWriterListener : public BRepositoryWriterListener { 31 public: 32 RepositoryWriterListener(bool verbose, bool quiet) 33 : fVerbose(verbose), fQuiet(quiet) 34 { 35 } 36 37 virtual void PrintErrorVarArgs(const char* format, va_list args) 38 { 39 vfprintf(stderr, format, args); 40 } 41 42 virtual void OnPackageAdded(const BPackageInfo& packageInfo) 43 { 44 if (fQuiet) 45 return; 46 47 printf("%s (%s)\n", packageInfo.Name().String(), 48 packageInfo.Version().ToString().String()); 49 if (fVerbose) { 50 printf("\tsummary: %s\n", packageInfo.Summary().String()); 51 printf("\tvendor: %s\n", packageInfo.Vendor().String()); 52 printf("\tpackager: %s\n", packageInfo.Packager().String()); 53 printf("\tchecksum: %s\n", packageInfo.Checksum().String()); 54 if (uint32 flags = packageInfo.Flags()) { 55 printf("\tflags:\n"); 56 if ((flags & B_PACKAGE_FLAG_APPROVE_LICENSE) != 0) 57 printf("\t\tapprove_license\n"); 58 if ((flags & B_PACKAGE_FLAG_SYSTEM_PACKAGE) != 0) 59 printf("\t\tsystem_package\n"); 60 } 61 } else 62 printf("\tchecksum: %s\n", packageInfo.Checksum().String()); 63 } 64 65 virtual void OnRepositoryInfoSectionDone(uint32 uncompressedSize) 66 { 67 if (fQuiet || !fVerbose) 68 return; 69 70 printf("----- Repository Info Section --------------------\n"); 71 printf("repository info size: %10" B_PRIu32 " (uncompressed)\n", 72 uncompressedSize); 73 } 74 75 virtual void OnPackageAttributesSectionDone(uint32 stringCount, 76 uint32 uncompressedSize) 77 { 78 if (fQuiet || !fVerbose) 79 return; 80 81 printf("----- Package Attribute Section -------------------\n"); 82 printf("string count: %10" B_PRIu32 "\n", stringCount); 83 printf("package attributes size: %10" B_PRIu32 " (uncompressed)\n", 84 uncompressedSize); 85 } 86 87 virtual void OnRepositoryDone(uint32 headerSize, uint32 repositoryInfoSize, 88 uint32 licenseCount, uint32 packageCount, uint32 packageAttributesSize, 89 uint64 totalSize) 90 { 91 if (fQuiet) 92 return; 93 94 printf("----- Package Repository Info -----\n"); 95 if (fVerbose) 96 printf("embedded license count %10" B_PRIu32 "\n", licenseCount); 97 printf("package count %10" B_PRIu32 "\n", packageCount); 98 printf("-----------------------------------\n"); 99 printf("header size: %10" B_PRIu32 "\n", headerSize); 100 printf("repository header size: %10" B_PRIu32 "\n", 101 repositoryInfoSize); 102 printf("package attributes size: %10" B_PRIu32 "\n", 103 packageAttributesSize); 104 printf("total size: %10" B_PRIu64 "\n", totalSize); 105 printf("-----------------------------------\n"); 106 } 107 108 private: 109 bool fVerbose; 110 bool fQuiet; 111 }; 112 113 114 int 115 command_create(int argc, const char* const* argv) 116 { 117 const char* changeToDirectory = NULL; 118 bool quiet = false; 119 bool verbose = false; 120 121 while (true) { 122 static struct option sLongOptions[] = { 123 { "help", no_argument, 0, 'h' }, 124 { "quiet", no_argument, 0, 'q' }, 125 { "verbose", no_argument, 0, 'v' }, 126 { 0, 0, 0, 0 } 127 }; 128 129 opterr = 0; // don't print errors 130 int c = getopt_long(argc, (char**)argv, "+C:hqv", sLongOptions, NULL); 131 if (c == -1) 132 break; 133 134 switch (c) { 135 case 'C': 136 changeToDirectory = optarg; 137 break; 138 139 case 'h': 140 print_usage_and_exit(false); 141 break; 142 143 case 'q': 144 quiet = true; 145 break; 146 147 case 'v': 148 verbose = true; 149 break; 150 151 default: 152 print_usage_and_exit(true); 153 break; 154 } 155 } 156 157 // The remaining arguments are the repository info file plus one or more 158 // package files, i.e. at least two more arguments. 159 if (optind + 2 > argc) 160 print_usage_and_exit(true); 161 162 const char* repositoryInfoFileName = argv[optind++]; 163 const char* const* packageFileNames = argv + optind; 164 165 RepositoryWriterListener listener(verbose, quiet); 166 167 BEntry repositoryInfoEntry(repositoryInfoFileName); 168 if (!repositoryInfoEntry.Exists()) { 169 listener.PrintError( 170 "Error: given repository-info file '%s' doesn't exist!\n", 171 repositoryInfoFileName); 172 return 1; 173 } 174 175 // determine path for 'repo' file from given info file 176 BEntry repositoryParentEntry; 177 repositoryInfoEntry.GetParent(&repositoryParentEntry); 178 BPath repositoryPath; 179 if (repositoryParentEntry.GetPath(&repositoryPath) != B_OK) { 180 listener.PrintError( 181 "Error: can't determine path of given repository-info file!\n"); 182 return 1; 183 } 184 repositoryPath.Append("repo"); 185 186 // create repository 187 BRepositoryInfo repositoryInfo(repositoryInfoEntry); 188 status_t result = repositoryInfo.InitCheck(); 189 if (result != B_OK) { 190 listener.PrintError( 191 "Error: can't parse given repository-info file : %s\n", 192 strerror(result)); 193 return 1; 194 } 195 BRepositoryWriter repositoryWriter(&listener, &repositoryInfo); 196 if ((result = repositoryWriter.Init(repositoryPath.Path())) != B_OK) { 197 listener.PrintError("Error: can't initialize repository-writer : %s\n", 198 strerror(result)); 199 return 1; 200 } 201 202 // change directory, if requested 203 if (changeToDirectory != NULL) { 204 if (chdir(changeToDirectory) != 0) { 205 listener.PrintError( 206 "Error: Failed to change the current working directory to " 207 "\"%s\": %s\n", changeToDirectory, strerror(errno)); 208 return 1; 209 } 210 } 211 212 // add all given package files 213 for (int i = 0; i < argc - optind; ++i) { 214 if (verbose) 215 printf("reading package '%s' ...\n", packageFileNames[i]); 216 BEntry entry(packageFileNames[i]); 217 if (!entry.Exists()) { 218 printf("package '%s' does not exist\n", packageFileNames[i]); 219 return 1; 220 } 221 result = repositoryWriter.AddPackage(entry); 222 if (result != B_OK) 223 return 1; 224 } 225 226 // write the repository 227 result = repositoryWriter.Finish(); 228 if (result != B_OK) 229 return 1; 230 231 if (verbose) { 232 printf("\nsuccessfully created repository '%s'\n", 233 repositoryPath.Path()); 234 } 235 236 return 0; 237 } 238