merge-file: add an option to process object IDs
git merge-file knows how to merge files on the file system already. It would be helpful, however, to allow it to also merge single blobs. Teach it an `--object-id` option which means that its arguments are object IDs and not files to allow it to do so. We handle the empty blob specially since read_mmblob doesn't read it directly and otherwise users cannot specify an empty ancestor. Signed-off-by: brian m. carlson <bk2204@github.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
8077612ea1
commit
e1068f0ad4
@ -1,5 +1,8 @@
|
||||
#include "builtin.h"
|
||||
#include "abspath.h"
|
||||
#include "hex.h"
|
||||
#include "object-name.h"
|
||||
#include "object-store.h"
|
||||
#include "config.h"
|
||||
#include "gettext.h"
|
||||
#include "setup.h"
|
||||
@ -31,10 +34,11 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
|
||||
mmfile_t mmfs[3] = { 0 };
|
||||
mmbuffer_t result = { 0 };
|
||||
xmparam_t xmp = { 0 };
|
||||
int ret = 0, i = 0, to_stdout = 0;
|
||||
int ret = 0, i = 0, to_stdout = 0, object_id = 0;
|
||||
int quiet = 0;
|
||||
struct option options[] = {
|
||||
OPT_BOOL('p', "stdout", &to_stdout, N_("send results to standard output")),
|
||||
OPT_BOOL(0, "object-id", &object_id, N_("use object IDs instead of filenames")),
|
||||
OPT_SET_INT(0, "diff3", &xmp.style, N_("use a diff3 based merge"), XDL_MERGE_DIFF3),
|
||||
OPT_SET_INT(0, "zdiff3", &xmp.style, N_("use a zealous diff3 based merge"),
|
||||
XDL_MERGE_ZEALOUS_DIFF3),
|
||||
@ -71,8 +75,12 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
|
||||
return error_errno("failed to redirect stderr to /dev/null");
|
||||
}
|
||||
|
||||
if (object_id)
|
||||
setup_git_directory();
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
char *fname;
|
||||
struct object_id oid;
|
||||
mmfile_t *mmf = mmfs + i;
|
||||
|
||||
if (!names[i])
|
||||
@ -80,12 +88,22 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
|
||||
|
||||
fname = prefix_filename(prefix, argv[i]);
|
||||
|
||||
if (read_mmfile(mmf, fname))
|
||||
if (object_id) {
|
||||
if (repo_get_oid(the_repository, argv[i], &oid))
|
||||
ret = error(_("object '%s' does not exist"),
|
||||
argv[i]);
|
||||
else if (!oideq(&oid, the_hash_algo->empty_blob))
|
||||
read_mmblob(mmf, &oid);
|
||||
else
|
||||
read_mmfile(mmf, "/dev/null");
|
||||
} else if (read_mmfile(mmf, fname)) {
|
||||
ret = -1;
|
||||
else if (mmf->size > MAX_XDIFF_SIZE ||
|
||||
buffer_is_binary(mmf->ptr, mmf->size))
|
||||
}
|
||||
if (ret != -1 && (mmf->size > MAX_XDIFF_SIZE ||
|
||||
buffer_is_binary(mmf->ptr, mmf->size))) {
|
||||
ret = error("Cannot merge binary files: %s",
|
||||
argv[i]);
|
||||
}
|
||||
|
||||
free(fname);
|
||||
if (ret)
|
||||
@ -99,20 +117,32 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
|
||||
ret = xdl_merge(mmfs + 1, mmfs + 0, mmfs + 2, &xmp, &result);
|
||||
|
||||
if (ret >= 0) {
|
||||
const char *filename = argv[0];
|
||||
char *fpath = prefix_filename(prefix, argv[0]);
|
||||
FILE *f = to_stdout ? stdout : fopen(fpath, "wb");
|
||||
if (object_id && !to_stdout) {
|
||||
struct object_id oid;
|
||||
if (result.size) {
|
||||
if (write_object_file(result.ptr, result.size, OBJ_BLOB, &oid) < 0)
|
||||
ret = error(_("Could not write object file"));
|
||||
} else {
|
||||
oidcpy(&oid, the_hash_algo->empty_blob);
|
||||
}
|
||||
if (ret >= 0)
|
||||
printf("%s\n", oid_to_hex(&oid));
|
||||
} else {
|
||||
const char *filename = argv[0];
|
||||
char *fpath = prefix_filename(prefix, argv[0]);
|
||||
FILE *f = to_stdout ? stdout : fopen(fpath, "wb");
|
||||
|
||||
if (!f)
|
||||
ret = error_errno("Could not open %s for writing",
|
||||
filename);
|
||||
else if (result.size &&
|
||||
fwrite(result.ptr, result.size, 1, f) != 1)
|
||||
ret = error_errno("Could not write to %s", filename);
|
||||
else if (fclose(f))
|
||||
ret = error_errno("Could not close %s", filename);
|
||||
if (!f)
|
||||
ret = error_errno("Could not open %s for writing",
|
||||
filename);
|
||||
else if (result.size &&
|
||||
fwrite(result.ptr, result.size, 1, f) != 1)
|
||||
ret = error_errno("Could not write to %s", filename);
|
||||
else if (fclose(f))
|
||||
ret = error_errno("Could not close %s", filename);
|
||||
free(fpath);
|
||||
}
|
||||
free(result.ptr);
|
||||
free(fpath);
|
||||
}
|
||||
|
||||
if (ret > 127)
|
||||
|
Reference in New Issue
Block a user