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