static void stuff_change(struct diff_options *opt, unsigned old_mode, unsigned new_mode, const unsigned char *old_sha1, const unsigned char *new_sha1, const char *old_name, const char *new_name) { struct diff_filespec *one, *two; if (!is_null_sha1(old_sha1) && !is_null_sha1(new_sha1) && !hashcmp(old_sha1, new_sha1) && (old_mode == new_mode)) return; if (DIFF_OPT_TST(opt, REVERSE_DIFF)) { unsigned tmp; const unsigned char *tmp_u; const char *tmp_c; tmp = old_mode; old_mode = new_mode; new_mode = tmp; tmp_u = old_sha1; old_sha1 = new_sha1; new_sha1 = tmp_u; tmp_c = old_name; old_name = new_name; new_name = tmp_c; } if (opt->prefix && (strncmp(old_name, opt->prefix, opt->prefix_length) || strncmp(new_name, opt->prefix, opt->prefix_length))) return; one = alloc_filespec(old_name); two = alloc_filespec(new_name); fill_filespec(one, old_sha1, old_mode); fill_filespec(two, new_sha1, new_mode); diff_queue(&diff_queued_diff, one, two); }
static void stuff_change(struct diff_options *opt, unsigned old_mode, unsigned new_mode, const struct object_id *old_oid, const struct object_id *new_oid, int old_oid_valid, int new_oid_valid, const char *old_path, const char *new_path) { struct diff_filespec *one, *two; if (!is_null_oid(old_oid) && !is_null_oid(new_oid) && !oidcmp(old_oid, new_oid) && (old_mode == new_mode)) return; if (opt->flags.reverse_diff) { SWAP(old_mode, new_mode); SWAP(old_oid, new_oid); SWAP(old_path, new_path); } if (opt->prefix && (strncmp(old_path, opt->prefix, opt->prefix_length) || strncmp(new_path, opt->prefix, opt->prefix_length))) return; one = alloc_filespec(old_path); two = alloc_filespec(new_path); fill_filespec(one, old_oid, old_oid_valid, old_mode); fill_filespec(two, new_oid, new_oid_valid, new_mode); diff_queue(&diff_queued_diff, one, two); }
static struct diff_filespec *noindex_filespec(const char *name, int mode) { struct diff_filespec *s; if (!name) name = "/dev/null"; s = alloc_filespec(name); fill_filespec(s, null_sha1, 0, mode); if (name == file_from_standard_input) populate_from_stdin(s); return s; }
static struct diff_filespec *get_filespec(const char *name, const char *p) { struct diff_filespec *spec = alloc_filespec(name); fill_filespec(spec, &null_oid, 0, 0644); spec->data = (char *)p; spec->size = strlen(p); spec->should_munmap = 0; spec->is_stdin = 1; spec->driver = &no_func_name; return spec; }
static int fill_textconv_grep(struct userdiff_driver *driver, struct grep_source *gs) { struct diff_filespec *df; char *buf; size_t size; if (!driver || !driver->textconv) return grep_source_load(gs); /* * The textconv interface is intimately tied to diff_filespecs, so we * have to pretend to be one. If we could unify the grep_source * and diff_filespec structs, this mess could just go away. */ df = alloc_filespec(gs->path); switch (gs->type) { case GREP_SOURCE_SHA1: fill_filespec(df, gs->identifier, 1, 0100644); break; case GREP_SOURCE_FILE: fill_filespec(df, null_sha1, 0, 0100644); break; default: die("BUG: attempt to textconv something without a path?"); } /* * fill_textconv is not remotely thread-safe; it may load objects * behind the scenes, and it modifies the global diff tempfile * structure. */ grep_read_lock(); size = fill_textconv(driver, df, &buf); grep_read_unlock(); free_filespec(df); /* * The normal fill_textconv usage by the diff machinery would just keep * the textconv'd buf separate from the diff_filespec. But much of the * grep code passes around a grep_source and assumes that its "buf" * pointer is the beginning of the thing we are searching. So let's * install our textconv'd version into the grep_source, taking care not * to leak any existing buffer. */ grep_source_clear_data(gs); gs->buf = buf; gs->size = size; return 0; }
static int queue_diff(struct diff_options *o, const char *name1, const char *name2) { int mode1 = 0, mode2 = 0; if (get_mode(name1, &mode1) || get_mode(name2, &mode2)) return -1; if (mode1 && mode2 && S_ISDIR(mode1) != S_ISDIR(mode2)) return error("file/directory conflict: %s, %s", name1, name2); if (S_ISDIR(mode1) || S_ISDIR(mode2)) { char buffer1[PATH_MAX], buffer2[PATH_MAX]; struct string_list p1 = {NULL, 0, 0, 1}, p2 = {NULL, 0, 0, 1}; int len1 = 0, len2 = 0, i1, i2, ret = 0; if (name1 && read_directory(name1, &p1)) return -1; if (name2 && read_directory(name2, &p2)) { string_list_clear(&p1, 0); return -1; } if (name1) { len1 = strlen(name1); if (len1 > 0 && name1[len1 - 1] == '/') len1--; memcpy(buffer1, name1, len1); buffer1[len1++] = '/'; } if (name2) { len2 = strlen(name2); if (len2 > 0 && name2[len2 - 1] == '/') len2--; memcpy(buffer2, name2, len2); buffer2[len2++] = '/'; } for (i1 = i2 = 0; !ret && (i1 < p1.nr || i2 < p2.nr); ) { const char *n1, *n2; int comp; if (i1 == p1.nr) comp = 1; else if (i2 == p2.nr) comp = -1; else comp = strcmp(p1.items[i1].string, p2.items[i2].string); if (comp > 0) n1 = NULL; else { n1 = buffer1; strncpy(buffer1 + len1, p1.items[i1++].string, PATH_MAX - len1); } if (comp < 0) n2 = NULL; else { n2 = buffer2; strncpy(buffer2 + len2, p2.items[i2++].string, PATH_MAX - len2); } ret = queue_diff(o, n1, n2); } string_list_clear(&p1, 0); string_list_clear(&p2, 0); return ret; } else { struct diff_filespec *d1, *d2; if (DIFF_OPT_TST(o, REVERSE_DIFF)) { unsigned tmp; const char *tmp_c; tmp = mode1; mode1 = mode2; mode2 = tmp; tmp_c = name1; name1 = name2; name2 = tmp_c; } if (!name1) name1 = "/dev/null"; if (!name2) name2 = "/dev/null"; d1 = alloc_filespec(name1); d2 = alloc_filespec(name2); fill_filespec(d1, null_sha1, mode1); fill_filespec(d2, null_sha1, mode2); diff_queue(&diff_queued_diff, d1, d2); return 0; } }