00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "pandabase.h"
00016 #include "panda_getopt.h"
00017 #include "preprocess_argv.h"
00018 #include "patchfile.h"
00019 #include "filename.h"
00020
00021 void
00022 usage() {
00023 cerr << "Usage: build_patch [opts] <old_file> <new_file>" << endl;
00024 }
00025
00026 void
00027 help() {
00028 usage();
00029 cerr << "\n"
00030 "This program generates a patch file that describes the differences\n"
00031 "between any two source files. The patch file can later be used to\n"
00032 "construct <new_file>, given <old_file>. Arbitrary file types, including\n"
00033 "binary files, are supported.\n\n"
00034
00035 "The patching algorithm can get very slow for very large files. As an\n"
00036 "optimization, if the input files are both Panda Multifiles, the patcher\n"
00037 "will by default patch them on a per-subfile basis, which has the potential\n"
00038 "to be much faster. The -c option will forbid this and force the patcher\n"
00039 "to work on the full file.\n\n"
00040
00041 "Options:\n\n"
00042
00043 " -o output_name\n"
00044 " Specify the filename of the patch file to generate.\n\n"
00045
00046 " -c\n"
00047 " Always generate patches against the complete file, even if the\n"
00048 " input files appear to be multifiles.\n\n"
00049
00050 " -f footprint_length\n"
00051 " Specify the footprint length for the patching algorithm.\n\n";
00052 }
00053
00054 int
00055 main(int argc, char **argv) {
00056 Filename patch_file;
00057 bool complete_file = false;
00058 int footprint_length = 0;
00059
00060
00061 extern int optind;
00062 static const char *optflags = "o:cf:h";
00063 preprocess_argv(argc, argv);
00064 int flag = getopt(argc, argv, optflags);
00065 Filename rel_path;
00066 while (flag != EOF) {
00067 switch (flag) {
00068 case 'o':
00069 patch_file = optarg;
00070 break;
00071
00072 case 'c':
00073 complete_file = true;
00074 break;
00075
00076 case 'f':
00077 footprint_length = atoi(optarg);
00078 break;
00079
00080 case 'h':
00081 help();
00082 return 1;
00083 case '?':
00084 usage();
00085 return 1;
00086 default:
00087 cerr << "Unhandled switch: " << flag << endl;
00088 break;
00089 }
00090 flag = getopt(argc, argv, optflags);
00091 }
00092 argc -= (optind - 1);
00093 argv += (optind - 1);
00094
00095 if (argc < 3) {
00096 usage();
00097 return 1;
00098 }
00099
00100 Filename src_file = Filename::from_os_specific(argv[1]);
00101 src_file.set_binary();
00102
00103 Filename dest_file = Filename::from_os_specific(argv[2]);
00104 dest_file.set_binary();
00105
00106 if (patch_file.empty()) {
00107 patch_file = dest_file.get_fullpath() + ".pch";
00108 }
00109 Patchfile pfile;
00110
00111 pfile.set_allow_multifile(!complete_file);
00112 if (footprint_length != 0) {
00113 cerr << "Footprint length is " << footprint_length << "\n";
00114 pfile.set_footprint_length(footprint_length);
00115 }
00116
00117 cerr << "Building patch file to convert " << src_file << " to "
00118 << dest_file << endl;
00119 if (pfile.build(src_file, dest_file, patch_file) == false) {
00120 cerr << "build patch failed" << endl;
00121 return 1;
00122 }
00123
00124 return 0;
00125 }