#
# Define NO_STRLCPY if you don't have strlcpy.
#
++# Define NO_STRTOUMAX if you don't have strtoumax in the C library.
++# If your compiler also does not support long long or does not have
++# strtoull, define NO_STRTOULL.
++#
# Define NO_SETENV if you don't have setenv in the C library.
#
# Define NO_SYMLINK_HEAD if you never want .git/HEAD to be a symbolic link.
git-merge-one-file.sh git-parse-remote.sh \
git-pull.sh git-rebase.sh \
git-repack.sh git-request-pull.sh git-reset.sh \
-- git-resolve.sh git-revert.sh git-sh-setup.sh \
++ git-revert.sh git-sh-setup.sh \
git-tag.sh git-verify-tag.sh \
git-applymbox.sh git-applypatch.sh git-am.sh \
git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \
revision.o pager.o tree-walk.o xdiff-interface.o \
write_or_die.o trace.o list-objects.o grep.o \
alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \
- - color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o
+ + color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
+ + convert.o
BUILTIN_OBJS = \
builtin-add.o \
builtin-diff.o \
builtin-diff-files.o \
builtin-diff-index.o \
-- builtin-diff-stages.o \
builtin-diff-tree.o \
builtin-fmt-merge-msg.o \
builtin-for-each-ref.o \
builtin-ls-tree.o \
builtin-mailinfo.o \
builtin-mailsplit.o \
++ builtin-merge-base.o \
builtin-merge-file.o \
builtin-mv.o \
builtin-name-rev.o \
NO_UNSETENV = YesPlease
NO_SETENV = YesPlease
NO_C99_FORMAT = YesPlease
++ NO_STRTOUMAX = YesPlease
endif
ifeq ($(uname_R),5.9)
NO_UNSETENV = YesPlease
NO_SETENV = YesPlease
NO_C99_FORMAT = YesPlease
++ NO_STRTOUMAX = YesPlease
endif
INSTALL = ginstall
TAR = gtar
COMPAT_CFLAGS += -DNO_STRLCPY
COMPAT_OBJS += compat/strlcpy.o
endif
++ifdef NO_STRTOUMAX
++ COMPAT_CFLAGS += -DNO_STRTOUMAX
++ COMPAT_OBJS += compat/strtoumax.o
++endif
++ifdef NO_STRTOULL
++ COMPAT_CFLAGS += -DNO_STRTOULL
++endif
ifdef NO_SETENV
COMPAT_CFLAGS += -DNO_SETENV
COMPAT_OBJS += compat/setenv.o
$(TAR) rf $(GIT_TARNAME).tar \
$(GIT_TARNAME)/git.spec \
$(GIT_TARNAME)/version \
-- $(GIT_TARNAME)/git-gui/version
++ $(GIT_TARNAME)/git-gui/version \
++ $(GIT_TARNAME)/git-gui/credits
@rm -rf $(GIT_TARNAME)
gzip -f -9 $(GIT_TARNAME).tar
case "$$v" in \
git-merge-octopus | git-merge-ours | git-merge-recursive | \
git-merge-resolve | git-merge-stupid | \
++ git-add--interactive | git-fsck-objects | git-init-db | \
++ git-repo-config | \
git-ssh-pull | git-ssh-push ) continue ;; \
esac ; \
test -f "Documentation/$$v.txt" || \
echo "no doc: $$v"; \
-- grep -q "^gitlink:$$v\[[0-9]\]::" Documentation/git.txt || \
++ sed -e '1,/^__DATA__/d' Documentation/cmd-list.perl | \
++ grep -q "^$$v[ ]" || \
case "$$v" in \
git) ;; \
*) echo "no link: $$v";; \
static int unidiff_zero;
static int p_value = 1;
++ static int p_value_known;
static int check_index;
static int write_index;
static int cached;
unsigned long deflate_origlen;
int lines_added, lines_deleted;
int score;
++ unsigned int is_toplevel_relative:1;
unsigned int inaccurate_eof:1;
unsigned int is_binary:1;
unsigned int is_copy:1;
return 1;
}
-- static char * find_name(const char *line, char *def, int p_value, int terminate)
++ static char *find_name(const char *line, char *def, int p_value, int terminate)
{
int len;
const char *start = line;
return name;
}
++ static int count_slashes(const char *cp)
++ {
++ int cnt = 0;
++ char ch;
++
++ while ((ch = *cp++))
++ if (ch == '/')
++ cnt++;
++ return cnt;
++ }
++
++ /*
++ * Given the string after "--- " or "+++ ", guess the appropriate
++ * p_value for the given patch.
++ */
++ static int guess_p_value(const char *nameline)
++ {
++ char *name, *cp;
++ int val = -1;
++
++ if (is_dev_null(nameline))
++ return -1;
++ name = find_name(nameline, NULL, 0, TERM_SPACE | TERM_TAB);
++ if (!name)
++ return -1;
++ cp = strchr(name, '/');
++ if (!cp)
++ val = 0;
++ else if (prefix) {
++ /*
++ * Does it begin with "a/$our-prefix" and such? Then this is
++ * very likely to apply to our directory.
++ */
++ if (!strncmp(name, prefix, prefix_length))
++ val = count_slashes(prefix);
++ else {
++ cp++;
++ if (!strncmp(cp, prefix, prefix_length))
++ val = count_slashes(prefix) + 1;
++ }
++ }
++ free(name);
++ return val;
++ }
++
/*
* Get the name etc info from the --/+++ lines of a traditional patch header
*
-- * NOTE! This hardcodes "-p1" behaviour in filename detection.
-- *
* FIXME! The end-of-filename heuristics are kind of screwy. For existing
* files, we can happily check the index for a match, but for creating a
* new file we should try to match whatever "patch" does. I have no idea.
first += 4; /* skip "--- " */
second += 4; /* skip "+++ " */
++ if (!p_value_known) {
++ int p, q;
++ p = guess_p_value(first);
++ q = guess_p_value(second);
++ if (p < 0) p = q;
++ if (0 <= p && p == q) {
++ p_value = p;
++ p_value_known = 1;
++ }
++ }
if (is_dev_null(first)) {
patch->is_new = 1;
patch->is_delete = 0;
{
unsigned long offset, len;
++ patch->is_toplevel_relative = 0;
patch->is_rename = patch->is_copy = 0;
patch->is_new = patch->is_delete = -1;
patch->old_mode = patch->new_mode = 0;
die("git diff header lacks filename information (line %d)", linenr);
patch->old_name = patch->new_name = patch->def_name;
}
++ patch->is_toplevel_relative = 1;
*hdrsize = git_hdr_len;
return offset;
}
*status_p = 0;
-- if (!strncmp(buffer, "delta ", 6)) {
++ if (!prefixcmp(buffer, "delta ")) {
patch_method = BINARY_DELTA_DEFLATED;
origlen = strtoul(buffer + 6, NULL, 10);
}
-- else if (!strncmp(buffer, "literal ", 8)) {
++ else if (!prefixcmp(buffer, "literal ")) {
patch_method = BINARY_LITERAL_DEFLATED;
origlen = strtoul(buffer + 8, NULL, 10);
}
free(qname);
}
- -static int read_old_data(struct stat *st, const char *path, void *buf, unsigned long size)
+ +static int read_old_data(struct stat *st, const char *path, char **buf_p, unsigned long *alloc_p, unsigned long *size_p)
{
int fd;
unsigned long got;
+ + unsigned long nsize;
+ + char *nbuf;
+ + unsigned long size = *size_p;
+ + char *buf = *buf_p;
switch (st->st_mode & S_IFMT) {
case S_IFLNK:
- - return readlink(path, buf, size);
+ + return readlink(path, buf, size) != size;
case S_IFREG:
fd = open(path, O_RDONLY);
if (fd < 0)
return error("unable to open %s", path);
got = 0;
for (;;) {
- - int ret = xread(fd, (char *) buf + got, size - got);
+ + int ret = xread(fd, buf + got, size - got);
if (ret <= 0)
break;
got += ret;
}
close(fd);
- - return got;
- -
+ + nsize = got;
+ + nbuf = buf;
+ + if (convert_to_git(path, &nbuf, &nsize)) {
+ + free(buf);
+ + *buf_p = nbuf;
+ + *alloc_p = nsize;
+ + *size_p = nsize;
+ + }
+ + return got != size;
default:
return -1;
}
size = st->st_size;
alloc = size + 8192;
buf = xmalloc(alloc);
- - if (read_old_data(st, patch->old_name, buf, alloc) != size)
+ + if (read_old_data(st, patch->old_name, &buf, &alloc, &size))
return error("read of %s failed", patch->old_name);
}
return error("%s: %s", old_name, strerror(errno));
if (!cached)
-- st_mode = ntohl(create_ce_mode(st.st_mode));
++ st_mode = ntohl(ce_mode_from_stat(ce, st.st_mode));
if (patch->is_new < 0)
patch->is_new = 0;
}
}
-- static void remove_file(struct patch *patch)
++ static void remove_file(struct patch *patch, int rmdir_empty)
{
if (write_index) {
if (remove_file_from_cache(patch->old_name) < 0)
cache_tree_invalidate_path(active_cache_tree, patch->old_name);
}
if (!cached) {
-- if (!unlink(patch->old_name)) {
++ if (!unlink(patch->old_name) && rmdir_empty) {
char *name = xstrdup(patch->old_name);
char *end = strrchr(name, '/');
while (end) {
static int try_create_file(const char *path, unsigned int mode, const char *buf, unsigned long size)
{
int fd;
+ + char *nbuf;
+ + unsigned long nsize;
if (S_ISLNK(mode))
/* Although buf:size is counted string, it also is NUL
* terminated.
*/
return symlink(buf, path);
+ + nsize = size;
+ + nbuf = (char *) buf;
+ + if (convert_to_working_tree(path, &nbuf, &nsize)) {
+ + free((char *) buf);
+ + buf = nbuf;
+ + size = nsize;
+ + }
+ +
fd = open(path, O_CREAT | O_EXCL | O_WRONLY, (mode & 0100) ? 0777 : 0666);
if (fd < 0)
return -1;
{
if (patch->is_delete > 0) {
if (phase == 0)
-- remove_file(patch);
++ remove_file(patch, 1);
return;
}
if (patch->is_new > 0 || patch->is_copy) {
* thing: remove the old, write the new
*/
if (phase == 0)
-- remove_file(patch);
++ remove_file(patch, 0);
if (phase == 1)
create_file(patch);
}
return 1;
}
++ static void prefix_one(char **name)
++ {
++ char *old_name = *name;
++ if (!old_name)
++ return;
++ *name = xstrdup(prefix_filename(prefix, prefix_length, *name));
++ free(old_name);
++ }
++
++ static void prefix_patches(struct patch *p)
++ {
++ if (!prefix || p->is_toplevel_relative)
++ return;
++ for ( ; p; p = p->next) {
++ if (p->new_name == p->old_name) {
++ char *prefixed = p->new_name;
++ prefix_one(&prefixed);
++ p->new_name = p->old_name = prefixed;
++ }
++ else {
++ prefix_one(&p->new_name);
++ prefix_one(&p->old_name);
++ }
++ }
++ }
++
static int apply_patch(int fd, const char *filename, int inaccurate_eof)
{
unsigned long offset, size;
break;
if (apply_in_reverse)
reverse_patches(patch);
++ if (prefix)
++ prefix_patches(patch);
if (use_patch(patch)) {
patch_stats(patch);
*listp = patch;
listp = &patch->next;
-- } else {
++ }
++ else {
/* perhaps free it a bit better? */
free(patch);
skipped_patch++;
int read_stdin = 1;
int inaccurate_eof = 0;
int errs = 0;
++ int is_not_gitdir = 0;
const char *whitespace_option = NULL;
++ prefix = setup_git_directory_gently(&is_not_gitdir);
++ prefix_length = prefix ? strlen(prefix) : 0;
++ git_config(git_apply_config);
++ if (apply_default_whitespace)
++ parse_whitespace_option(apply_default_whitespace);
+
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
char *end;
read_stdin = 0;
continue;
}
-- if (!strncmp(arg, "--exclude=", 10)) {
++ if (!prefixcmp(arg, "--exclude=")) {
struct excludes *x = xmalloc(sizeof(*x));
x->path = arg + 10;
x->next = excludes;
excludes = x;
continue;
}
-- if (!strncmp(arg, "-p", 2)) {
++ if (!prefixcmp(arg, "-p")) {
p_value = atoi(arg + 2);
++ p_value_known = 1;
continue;
}
if (!strcmp(arg, "--no-add")) {
continue;
}
if (!strcmp(arg, "--index")) {
++ if (is_not_gitdir)
++ die("--index outside a repository");
check_index = 1;
continue;
}
if (!strcmp(arg, "--cached")) {
++ if (is_not_gitdir)
++ die("--cached outside a repository");
check_index = 1;
cached = 1;
continue;
line_termination = 0;
continue;
}
-- if (!strncmp(arg, "-C", 2)) {
++ if (!prefixcmp(arg, "-C")) {
p_context = strtoul(arg + 2, &end, 0);
if (*end != '\0')
die("unrecognized context count '%s'", arg + 2);
continue;
}
-- if (!strncmp(arg, "--whitespace=", 13)) {
++ if (!prefixcmp(arg, "--whitespace=")) {
whitespace_option = arg + 13;
parse_whitespace_option(arg + 13);
continue;
inaccurate_eof = 1;
continue;
}
--
-- if (check_index && prefix_length < 0) {
-- prefix = setup_git_directory();
-- prefix_length = prefix ? strlen(prefix) : 0;
-- git_config(git_apply_config);
-- if (!whitespace_option && apply_default_whitespace)
-- parse_whitespace_option(apply_default_whitespace);
-- }
if (0 < prefix_length)
arg = prefix_filename(prefix, prefix_length, arg);
return htonl(S_IFLNK);
return htonl(S_IFREG | ce_permissions(mode));
}
++static inline unsigned int ce_mode_from_stat(struct cache_entry *ce, unsigned int mode)
++{
++ extern int trust_executable_bit;
++ if (!trust_executable_bit && S_ISREG(mode)) {
++ if (ce && S_ISREG(ntohl(ce->ce_mode)))
++ return ce->ce_mode;
++ return create_ce_mode(0666);
++ }
++ return create_ce_mode(mode);
++}
#define canon_mode(mode) \
(S_ISREG(mode) ? (S_IFREG | ce_permissions(mode)) : \
S_ISLNK(mode) ? S_IFLNK : S_IFDIR)
extern int zlib_compression_level;
extern size_t packed_git_window_size;
extern size_t packed_git_limit;
+ +extern int auto_crlf;
#define GIT_REPO_VERSION 0
extern int repository_format_version;
extern void trace_printf(const char *format, ...);
extern void trace_argv_printf(const char **argv, int count, const char *format, ...);
+ +/* convert.c */
+ +extern int convert_to_git(const char *path, char **bufp, unsigned long *sizep);
+ +extern int convert_to_working_tree(const char *path, char **bufp, unsigned long *sizep);
+ +
#endif /* CACHE_H */
}
if (!strcmp(var, "core.packedgitwindowsize")) {
-- int pgsz = getpagesize();
++ int pgsz_x2 = getpagesize() * 2;
packed_git_window_size = git_config_int(var, value);
-- packed_git_window_size /= pgsz;
-- if (packed_git_window_size < 2)
-- packed_git_window_size = 2;
-- packed_git_window_size *= pgsz;
++
++ /* This value must be multiple of (pagesize * 2) */
++ packed_git_window_size /= pgsz_x2;
++ if (packed_git_window_size < 1)
++ packed_git_window_size = 1;
++ packed_git_window_size *= pgsz_x2;
return 0;
}
return 0;
}
+ + if (!strcmp(var, "core.autocrlf")) {
+ + if (value && !strcasecmp(value, "input")) {
+ + auto_crlf = -1;
+ + return 0;
+ + }
+ + auto_crlf = git_config_bool(var, value);
+ + return 0;
+ + }
+ +
if (!strcmp(var, "user.name")) {
strlcpy(git_default_name, value, sizeof(git_default_name));
return 0;
diff_detect_rename_default = DIFF_DETECT_RENAME;
return 0;
}
-- if (!strncmp(var, "diff.color.", 11) || !strncmp(var, "color.diff.", 11)) {
++ if (!prefixcmp(var, "diff.color.") || !prefixcmp(var, "color.diff.")) {
int slot = parse_diff_color_slot(var, 11);
color_parse(value, var, diff_colors[slot]);
return 0;
}
}
--static void copy_file(int prefix, const char *data, int size)
++static void copy_file(int prefix, const char *data, int size,
++ const char *set, const char *reset)
{
int ch, nl_just_seen = 1;
while (0 < size--) {
ch = *data++;
-- if (nl_just_seen)
++ if (nl_just_seen) {
++ fputs(set, stdout);
putchar(prefix);
-- putchar(ch);
-- if (ch == '\n')
++ }
++ if (ch == '\n') {
nl_just_seen = 1;
-- else
++ fputs(reset, stdout);
++ } else
nl_just_seen = 0;
++ putchar(ch);
}
if (!nl_just_seen)
-- printf("\n\\ No newline at end of file\n");
++ printf("%s\n\\ No newline at end of file\n", reset);
}
static void emit_rewrite_diff(const char *name_a,
const char *name_b,
struct diff_filespec *one,
-- struct diff_filespec *two)
++ struct diff_filespec *two,
++ int color_diff)
{
int lc_a, lc_b;
++ const char *name_a_tab, *name_b_tab;
++ const char *metainfo = diff_get_color(color_diff, DIFF_METAINFO);
++ const char *fraginfo = diff_get_color(color_diff, DIFF_FRAGINFO);
++ const char *old = diff_get_color(color_diff, DIFF_FILE_OLD);
++ const char *new = diff_get_color(color_diff, DIFF_FILE_NEW);
++ const char *reset = diff_get_color(color_diff, DIFF_RESET);
++
++ name_a_tab = strchr(name_a, ' ') ? "\t" : "";
++ name_b_tab = strchr(name_b, ' ') ? "\t" : "";
++
diff_populate_filespec(one, 0);
diff_populate_filespec(two, 0);
lc_a = count_lines(one->data, one->size);
lc_b = count_lines(two->data, two->size);
-- printf("--- a/%s\n+++ b/%s\n@@ -", name_a, name_b);
++ printf("%s--- a/%s%s%s\n%s+++ b/%s%s%s\n%s@@ -",
++ metainfo, name_a, name_a_tab, reset,
++ metainfo, name_b, name_b_tab, reset, fraginfo);
print_line_count(lc_a);
printf(" +");
print_line_count(lc_b);
-- printf(" @@\n");
++ printf(" @@%s\n", reset);
if (lc_a)
-- copy_file('-', one->data, one->size);
++ copy_file('-', one->data, one->size, old, reset);
if (lc_b)
-- copy_file('+', two->data, two->size);
++ copy_file('+', two->data, two->size, new, reset);
}
static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)
puts(reset);
}
--static void emit_add_line(const char *reset, struct emit_callback *ecbdata, const char *line, int len)
++static void emit_line_with_ws(int nparents,
++ const char *set, const char *reset, const char *ws,
++ const char *line, int len)
{
-- int col0 = ecbdata->nparents;
++ int col0 = nparents;
int last_tab_in_indent = -1;
int last_space_in_indent = -1;
int i;
int tail = len;
int need_highlight_leading_space = 0;
-- const char *ws = diff_get_color(ecbdata->color_diff, DIFF_WHITESPACE);
-- const char *set = diff_get_color(ecbdata->color_diff, DIFF_FILE_NEW);
--
-- if (!*ws) {
-- emit_line(set, reset, line, len);
-- return;
-- }
--
/* The line is a newly added line. Does it have funny leading
* whitespaces? In indent, SP should never precede a TAB.
*/
emit_line(set, reset, line + i, len - i);
}
++static void emit_add_line(const char *reset, struct emit_callback *ecbdata, const char *line, int len)
++{
++ const char *ws = diff_get_color(ecbdata->color_diff, DIFF_WHITESPACE);
++ const char *set = diff_get_color(ecbdata->color_diff, DIFF_FILE_NEW);
++
++ if (!*ws)
++ emit_line(set, reset, line, len);
++ else
++ emit_line_with_ws(ecbdata->nparents, set, reset, ws,
++ line, len);
++}
++
static void fn_out_consume(void *priv, char *line, unsigned long len)
{
int i;
const char *reset = diff_get_color(ecbdata->color_diff, DIFF_RESET);
if (ecbdata->label_path[0]) {
-- printf("%s--- %s%s\n", set, ecbdata->label_path[0], reset);
-- printf("%s+++ %s%s\n", set, ecbdata->label_path[1], reset);
++ const char *name_a_tab, *name_b_tab;
++
++ name_a_tab = strchr(ecbdata->label_path[0], ' ') ? "\t" : "";
++ name_b_tab = strchr(ecbdata->label_path[1], ' ') ? "\t" : "";
++
++ printf("%s--- %s%s%s\n",
++ set, ecbdata->label_path[0], reset, name_a_tab);
++ printf("%s+++ %s%s%s\n",
++ set, ecbdata->label_path[1], reset, name_b_tab);
ecbdata->label_path[0] = ecbdata->label_path[1] = NULL;
}
struct checkdiff_t {
struct xdiff_emit_state xm;
const char *filename;
-- int lineno;
++ int lineno, color_diff;
};
static void checkdiff_consume(void *priv, char *line, unsigned long len)
{
struct checkdiff_t *data = priv;
++ const char *ws = diff_get_color(data->color_diff, DIFF_WHITESPACE);
++ const char *reset = diff_get_color(data->color_diff, DIFF_RESET);
++ const char *set = diff_get_color(data->color_diff, DIFF_FILE_NEW);
if (line[0] == '+') {
-- int i, spaces = 0;
++ int i, spaces = 0, space_before_tab = 0, white_space_at_end = 0;
/* check space before tab */
for (i = 1; i < len && (line[i] == ' ' || line[i] == '\t'); i++)
if (line[i] == ' ')
spaces++;
if (line[i - 1] == '\t' && spaces)
-- printf("%s:%d: space before tab:%.*s\n",
-- data->filename, data->lineno, (int)len, line);
++ space_before_tab = 1;
/* check white space at line end */
if (line[len - 1] == '\n')
len--;
if (isspace(line[len - 1]))
-- printf("%s:%d: white space at end: %.*s\n",
-- data->filename, data->lineno, (int)len, line);
++ white_space_at_end = 1;
++
++ if (space_before_tab || white_space_at_end) {
++ printf("%s:%d: %s", data->filename, data->lineno, ws);
++ if (space_before_tab) {
++ printf("space before tab");
++ if (white_space_at_end)
++ putchar(',');
++ }
++ if (white_space_at_end)
++ printf("white space at end");
++ printf(":%s ", reset);
++ emit_line_with_ws(1, set, reset, ws, line, len);
++ }
data->lineno++;
} else if (line[0] == ' ')
if ((one->mode ^ two->mode) & S_IFMT)
goto free_ab_and_return;
if (complete_rewrite) {
-- emit_rewrite_diff(name_a, name_b, one, two);
++ emit_rewrite_diff(name_a, name_b, one, two,
++ o->color_diff);
goto free_ab_and_return;
}
}
xecfg.flags = XDL_EMIT_FUNCNAMES;
if (!diffopts)
;
-- else if (!strncmp(diffopts, "--unified=", 10))
++ else if (!prefixcmp(diffopts, "--unified="))
xecfg.ctxlen = strtoul(diffopts + 10, NULL, 10);
-- else if (!strncmp(diffopts, "-u", 2))
++ else if (!prefixcmp(diffopts, "-u"))
xecfg.ctxlen = strtoul(diffopts + 2, NULL, 10);
ecb.outf = xdiff_outf;
ecb.priv = &ecbdata;
static void builtin_checkdiff(const char *name_a, const char *name_b,
struct diff_filespec *one,
-- struct diff_filespec *two)
++ struct diff_filespec *two, struct diff_options *o)
{
mmfile_t mf1, mf2;
struct checkdiff_t data;
data.xm.consume = checkdiff_consume;
data.filename = name_b ? name_b : name_a;
data.lineno = 0;
++ data.color_diff = o->color_diff;
if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
die("unable to read files to diff");
reuse_worktree_file(s->path, s->sha1, 0)) {
struct stat st;
int fd;
+ + char *buf;
+ + unsigned long size;
+ +
if (lstat(s->path, &st) < 0) {
if (errno == ENOENT) {
err_empty:
s->data = xmmap(NULL, s->size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
s->should_munmap = 1;
- - /* FIXME! CRLF -> LF conversion goes here, based on "s->path" */
+ +
+ + /*
+ + * Convert from working tree format to canonical git format
+ + */
+ + buf = s->data;
+ + size = s->size;
+ + if (convert_to_git(s->path, &buf, &size)) {
+ + munmap(s->data, s->size);
+ + s->should_munmap = 0;
+ + s->data = buf;
+ + s->size = size;
+ + s->should_free = 1;
+ + }
}
else {
char type[20];
diff_fill_sha1_info(p->one);
diff_fill_sha1_info(p->two);
-- builtin_checkdiff(name, other, p->one, p->two);
++ builtin_checkdiff(name, other, p->one, p->two, o);
}
void diff_setup(struct diff_options *options)
else if (!strcmp(arg, "--shortstat")) {
options->output_format |= DIFF_FORMAT_SHORTSTAT;
}
-- else if (!strncmp(arg, "--stat", 6)) {
++ else if (!prefixcmp(arg, "--stat")) {
char *end;
int width = options->stat_width;
int name_width = options->stat_name_width;
switch (*arg) {
case '-':
-- if (!strncmp(arg, "-width=", 7))
++ if (!prefixcmp(arg, "-width="))
width = strtoul(arg + 7, &end, 10);
-- else if (!strncmp(arg, "-name-width=", 12))
++ else if (!prefixcmp(arg, "-name-width="))
name_width = strtoul(arg + 12, &end, 10);
break;
case '=':
}
else if (!strcmp(arg, "-z"))
options->line_termination = 0;
-- else if (!strncmp(arg, "-l", 2))
++ else if (!prefixcmp(arg, "-l"))
options->rename_limit = strtoul(arg+2, NULL, 10);
else if (!strcmp(arg, "--full-index"))
options->full_index = 1;
options->output_format |= DIFF_FORMAT_NAME_STATUS;
else if (!strcmp(arg, "-R"))
options->reverse_diff = 1;
-- else if (!strncmp(arg, "-S", 2))
++ else if (!prefixcmp(arg, "-S"))
options->pickaxe = arg + 2;
else if (!strcmp(arg, "-s")) {
options->output_format |= DIFF_FORMAT_NO_OUTPUT;
}
-- else if (!strncmp(arg, "-O", 2))
++ else if (!prefixcmp(arg, "-O"))
options->orderfile = arg + 2;
-- else if (!strncmp(arg, "--diff-filter=", 14))
++ else if (!prefixcmp(arg, "--diff-filter="))
options->filter = arg + 14;
else if (!strcmp(arg, "--pickaxe-all"))
options->pickaxe_opts = DIFF_PICKAXE_ALL;
else if (!strcmp(arg, "--pickaxe-regex"))
options->pickaxe_opts = DIFF_PICKAXE_REGEX;
-- else if (!strncmp(arg, "-B", 2)) {
++ else if (!prefixcmp(arg, "-B")) {
if ((options->break_opt =
diff_scoreopt_parse(arg)) == -1)
return -1;
}
-- else if (!strncmp(arg, "-M", 2)) {
++ else if (!prefixcmp(arg, "-M")) {
if ((options->rename_score =
diff_scoreopt_parse(arg)) == -1)
return -1;
options->detect_rename = DIFF_DETECT_RENAME;
}
-- else if (!strncmp(arg, "-C", 2)) {
++ else if (!prefixcmp(arg, "-C")) {
if ((options->rename_score =
diff_scoreopt_parse(arg)) == -1)
return -1;
options->find_copies_harder = 1;
else if (!strcmp(arg, "--abbrev"))
options->abbrev = DEFAULT_ABBREV;
-- else if (!strncmp(arg, "--abbrev=", 9)) {
++ else if (!prefixcmp(arg, "--abbrev=")) {
options->abbrev = strtoul(arg + 9, NULL, 10);
if (options->abbrev < MINIMUM_ABBREV)
options->abbrev = MINIMUM_ABBREV;
options->xdl_opts |= XDF_IGNORE_WHITESPACE;
else if (!strcmp(arg, "-b") || !strcmp(arg, "--ignore-space-change"))
options->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE;
++ else if (!strcmp(arg, "--ignore-space-at-eol"))
++ options->xdl_opts |= XDF_IGNORE_WHITESPACE_AT_EOL;
else if (!strcmp(arg, "--color-words"))
options->color_diff = options->color_diff_words = 1;
else if (!strcmp(arg, "--no-renames"))
int new_len;
/* Ignore line numbers when computing the SHA1 of the patch */
-- if (!strncmp(line, "@@ -", 4))
++ if (!prefixcmp(line, "@@ -"))
return;
new_len = remove_space(line, len);
static unsigned int pack_open_windows;
static size_t peak_pack_mapped;
static size_t pack_mapped;
--static size_t page_size;
struct packed_git *packed_git;
void pack_report()
"pack_report: getpagesize() = %10" SZ_FMT "\n"
"pack_report: core.packedGitWindowSize = %10" SZ_FMT "\n"
"pack_report: core.packedGitLimit = %10" SZ_FMT "\n",
-- page_size,
++ (size_t) getpagesize(),
packed_git_window_size,
packed_git_limit);
fprintf(stderr,
break;
}
if (!win) {
-- if (!page_size)
-- page_size = getpagesize();
++ size_t window_align = packed_git_window_size / 2;
win = xcalloc(1, sizeof(*win));
-- win->offset = (offset / page_size) * page_size;
++ win->offset = (offset / window_align) * window_align;
win->len = p->pack_size - win->offset;
if (win->len > packed_git_window_size)
win->len = packed_git_window_size;
co = &cached_objects[cached_object_nr++];
co->size = len;
co->type = strdup(type);
++ co->buf = xmalloc(len);
++ memcpy(co->buf, buf, len);
hashcpy(co->sha1, sha1);
return 0;
}
--void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size)
++void *read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size)
{
unsigned long mapsize;
void *map, *buf;
{
unsigned long size = st->st_size;
void *buf;
- - int ret;
+ + int ret, re_allocated = 0;
buf = "";
if (size)
if (!type)
type = blob_type;
- - /* FIXME: CRLF -> LF conversion here for blobs! We'll need the path! */
+ +
+ + /*
+ + * Convert blobs to git internal format
+ + */
+ + if (!strcmp(type, blob_type)) {
+ + unsigned long nsize = size;
+ + char *nbuf = buf;
+ + if (convert_to_git(NULL, &nbuf, &nsize)) {
+ + if (size)
+ + munmap(buf, size);
+ + size = nsize;
+ + buf = nbuf;
+ + re_allocated = 1;
+ + }
+ + }
+ +
if (write_object)
ret = write_sha1_file(buf, size, type, sha1);
else
ret = hash_sha1_file(buf, size, type, sha1);
+ + if (re_allocated) {
+ + free(buf);
+ + return ret;
+ + }
if (size)
munmap(buf, size);
return ret;