Add "package add" command.

This commit is contained in:
Ingo Weinhold 2011-07-03 04:31:59 +02:00
parent 35f8c67c17
commit c1b5ec4065
5 changed files with 187 additions and 1 deletions

View File

@ -3,6 +3,7 @@ SubDir HAIKU_TOP src bin package ;
UsePrivateHeaders kernel shared ;
BinCommand package :
command_add.cpp
command_create.cpp
command_dump.cpp
command_extract.cpp

View File

@ -0,0 +1,165 @@
/*
* Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
* Distributed under the terms of the MIT License.
*/
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <Entry.h>
#include <package/PackageInfo.h>
#include <package/hpkg/HPKGDefs.h>
#include <package/hpkg/PackageWriter.h>
#include "package.h"
#include "PackageWriterListener.h"
#include "PackageWritingUtils.h"
#include "StandardErrorOutput.h"
using namespace BPackageKit::BHPKG;
int
command_add(int argc, const char* const* argv)
{
const char* changeToDirectory = NULL;
const char* packageInfoFileName = NULL;
bool quiet = false;
bool verbose = false;
bool force = false;
while (true) {
static struct option sLongOptions[] = {
{ "help", no_argument, 0, 'h' },
{ "quiet", no_argument, 0, 'q' },
{ "verbose", no_argument, 0, 'v' },
{ 0, 0, 0, 0 }
};
opterr = 0; // don't print errors
int c = getopt_long(argc, (char**)argv, "+C:fhi:qv", sLongOptions,
NULL);
if (c == -1)
break;
switch (c) {
case 'C':
changeToDirectory = optarg;
break;
case 'h':
print_usage_and_exit(false);
break;
case 'f':
force = true;
break;
case 'i':
packageInfoFileName = optarg;
break;
case 'q':
quiet = true;
break;
case 'v':
verbose = true;
break;
default:
print_usage_and_exit(true);
break;
}
}
// The remaining arguments are the package file and the entries to add.
if (optind >= argc)
print_usage_and_exit(true);
const char* packageFileName = argv[optind++];
// entries must be specified, if a .PackageInfo hasn't been specified via
// an option
if (optind >= argc && packageInfoFileName == NULL)
print_usage_and_exit(true);
const char* const* entriesToAdd = argv + optind;
int entriesToAddCount = argc - optind;
// create package
PackageWriterListener listener(verbose, quiet);
BPackageWriter packageWriter(&listener);
status_t result = packageWriter.Init(packageFileName,
B_HPKG_WRITER_UPDATE_PACKAGE | (force ? B_HPKG_WRITER_FORCE_ADD : 0));
if (result != B_OK)
return 1;
// If a package info file has been specified explicitly, open it.
int packageInfoFD = -1;
if (packageInfoFileName != NULL) {
packageInfoFD = open(packageInfoFileName, O_RDONLY);
if (packageInfoFD < 0) {
fprintf(stderr, "Error: Failed to open package info file \"%s\": "
"%s\n", packageInfoFileName, strerror(errno));
}
}
// change directory, if requested
if (changeToDirectory != NULL) {
if (chdir(changeToDirectory) != 0) {
listener.PrintError(
"Error: Failed to change the current working directory to "
"\"%s\": %s\n", changeToDirectory, strerror(errno));
}
}
// add the entries
for (int i = 0; i < entriesToAddCount; i++) {
const char* entry = entriesToAdd[i];
if (strcmp(entry, ".") == 0) {
// add all entries in the current directory; skip .PackageInfo,
// if a different file was specified
if (add_current_directory_entries(packageWriter,
listener, packageInfoFileName != NULL) != B_OK)
return 1;
} else {
// skip .PackageInfo, if a different file was specified
if (packageInfoFileName != NULL
&& strcmp(entry, B_HPKG_PACKAGE_INFO_FILE_NAME) == 0) {
continue;
}
if (packageWriter.AddEntry(entry) != B_OK)
return 1;
}
}
// add the .PackageInfo, if explicitly specified
if (packageInfoFileName != NULL) {
result = packageWriter.AddEntry(B_HPKG_PACKAGE_INFO_FILE_NAME,
packageInfoFD);
if (result != B_OK)
return 1;
}
// write the package
result = packageWriter.Finish();
if (result != B_OK)
return 1;
if (verbose)
printf("\nsuccessfully created package '%s'\n", packageFileName);
return 0;
}

View File

@ -23,10 +23,25 @@ static const char* kUsage =
"Creates, inspects, or extracts a Haiku package.\n"
"\n"
"Commands:\n"
" add [ <options> ] <package> <entries>...\n"
" Adds the specified entries <entries> to package file <package>.\n"
"\n"
" -C <dir> - Change to directory <dir> before adding entries.\n"
" -f - Force adding, replacing already existing entries. "
"Without\n"
" this option adding will fail when encountering a "
"pre-exiting\n"
" entry (directories will be merged, though).\n"
" -i <info> - Use the package info file <info>. It will be added as\n"
" \".PackageInfo\", overriding a \".PackageInfo\" file,\n"
" existing.\n"
" -q - Be quiet (don't show any output except for errors).\n"
" -v - Be verbose (show more info about created package).\n"
"\n"
" create [ <options> ] <package>\n"
" Creates package file <package> from contents of current directory.\n"
"\n"
" -C <dir> - Change to directory <dir> before starting.\n"
" -C <dir> - Change to directory <dir> before adding entries.\n"
" -i <info> - Use the package info file <info>. It will be added as\n"
" \".PackageInfo\", overriding a \".PackageInfo\" file,\n"
" existing.\n"
@ -71,6 +86,9 @@ main(int argc, const char* const* argv)
print_usage_and_exit(true);
const char* command = argv[1];
if (strcmp(command, "add") == 0)
return command_add(argc - 1, argv + 1);
if (strcmp(command, "create") == 0)
return command_create(argc - 1, argv + 1);

View File

@ -8,6 +8,7 @@
void print_usage_and_exit(bool error);
int command_add(int argc, const char* const* argv);
int command_create(int argc, const char* const* argv);
int command_dump(int argc, const char* const* argv);
int command_extract(int argc, const char* const* argv);

View File

@ -7,6 +7,7 @@ SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src bin package ] ;
USES_BE_API on <build>package = true ;
BuildPlatformMain <build>package :
command_add.cpp
command_create.cpp
command_dump.cpp
command_extract.cpp