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: %10lu (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: %10lu\n", stringCount); 83 printf("package attributes size: %10lu (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 %10lu\n", licenseCount); 97 printf("package count %10lu\n", packageCount); 98 printf("-----------------------------------\n"); 99 printf("header size: %10lu\n", headerSize); 100 printf("repository header size: %10lu\n", repositoryInfoSize); 101 printf("package attributes size: %10lu\n", packageAttributesSize); 102 printf("total size: %10llu\n", totalSize); 103 printf("-----------------------------------\n"); 104 } 105 106 private: 107 bool fVerbose; 108 bool fQuiet; 109 }; 110 111 112 int 113 command_create(int argc, const char* const* argv) 114 { 115 const char* changeToDirectory = NULL; 116 bool quiet = false; 117 bool verbose = false; 118 119 while (true) { 120 static struct option sLongOptions[] = { 121 { "help", no_argument, 0, 'h' }, 122 { "quiet", no_argument, 0, 'q' }, 123 { "verbose", no_argument, 0, 'v' }, 124 { 0, 0, 0, 0 } 125 }; 126 127 opterr = 0; // don't print errors 128 int c = getopt_long(argc, (char**)argv, "+C:hqv", sLongOptions, NULL); 129 if (c == -1) 130 break; 131 132 switch (c) { 133 case 'C': 134 changeToDirectory = optarg; 135 break; 136 137 case 'h': 138 print_usage_and_exit(false); 139 break; 140 141 case 'q': 142 quiet = true; 143 break; 144 145 case 'v': 146 verbose = true; 147 break; 148 149 default: 150 print_usage_and_exit(true); 151 break; 152 } 153 } 154 155 // The remaining arguments are the repository info file plus one or more 156 // package files, i.e. at least two more arguments. 157 if (optind + 2 > argc) 158 print_usage_and_exit(true); 159 160 const char* repositoryInfoFileName = argv[optind++]; 161 const char* const* packageFileNames = argv + optind; 162 163 RepositoryWriterListener listener(verbose, quiet); 164 165 BEntry repositoryInfoEntry(repositoryInfoFileName); 166 if (!repositoryInfoEntry.Exists()) { 167 listener.PrintError( 168 "Error: given repository-info file '%s' doesn't exist!\n", 169 repositoryInfoFileName); 170 return 1; 171 } 172 173 // determine path for 'repo' file from given info file 174 BEntry repositoryParentEntry; 175 repositoryInfoEntry.GetParent(&repositoryParentEntry); 176 BPath repositoryPath; 177 if (repositoryParentEntry.GetPath(&repositoryPath) != B_OK) { 178 listener.PrintError( 179 "Error: can't determine path of given repository-info file!\n"); 180 return 1; 181 } 182 repositoryPath.Append("repo"); 183 184 // create repository 185 BRepositoryInfo repositoryInfo(repositoryInfoEntry); 186 status_t result = repositoryInfo.InitCheck(); 187 if (result != B_OK) { 188 listener.PrintError( 189 "Error: can't parse given repository-info file : %s\n", 190 strerror(result)); 191 return 1; 192 } 193 BRepositoryWriter repositoryWriter(&listener, &repositoryInfo); 194 if ((result = repositoryWriter.Init(repositoryPath.Path())) != B_OK) { 195 listener.PrintError("Error: can't initialize repository-writer : %s\n", 196 strerror(result)); 197 return 1; 198 } 199 200 // change directory, if requested 201 if (changeToDirectory != NULL) { 202 if (chdir(changeToDirectory) != 0) { 203 listener.PrintError( 204 "Error: Failed to change the current working directory to " 205 "\"%s\": %s\n", changeToDirectory, strerror(errno)); 206 return 1; 207 } 208 } 209 210 // add all given package files 211 for (int i = 0; i < argc - optind; ++i) { 212 if (verbose) 213 printf("reading package '%s' ...\n", packageFileNames[i]); 214 BEntry entry(packageFileNames[i]); 215 result = repositoryWriter.AddPackage(entry); 216 if (result != B_OK) 217 return 1; 218 } 219 220 // write the repository 221 result = repositoryWriter.Finish(); 222 if (result != B_OK) 223 return 1; 224 225 if (verbose) { 226 printf("\nsuccessfully created repository '%s'\n", 227 repositoryPath.Path()); 228 } 229 230 return 0; 231 } 232