From: Junio C Hamano Date: Fri, 31 Oct 2008 01:08:58 +0000 (-0700) Subject: Merge branch 'ar/maint-mksnpath' into ar/mksnpath X-Git-Tag: v1.6.1-rc1~84^2 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/98b35e2c749614446b916230148d66857e8a09f3?ds=inline;hp=-c Merge branch 'ar/maint-mksnpath' into ar/mksnpath * ar/maint-mksnpath: Use git_pathdup instead of xstrdup(git_path(...)) git_pathdup: returns xstrdup-ed copy of the formatted path Fix potentially dangerous use of git_path in ref.c Add git_snpath: a .git path formatting routine with output buffer Conflicts: builtin-revert.c refs.c rerere.c --- 98b35e2c749614446b916230148d66857e8a09f3 diff --combined builtin-reflog.c index 6b3667ef0e,da96da317b..d95f515f2e --- a/builtin-reflog.c +++ b/builtin-reflog.c @@@ -277,11 -277,11 +277,11 @@@ static int expire_reflog(const char *re lock = lock_any_ref_for_update(ref, sha1, 0); if (!lock) return error("cannot lock ref '%s'", ref); - log_file = xstrdup(git_path("logs/%s", ref)); + log_file = git_pathdup("logs/%s", ref); if (!file_exists(log_file)) goto finish; if (!cmd->dry_run) { - newlog_path = xstrdup(git_path("logs/%s.lock", ref)); + newlog_path = git_pathdup("logs/%s.lock", ref); cb.newlog = fopen(newlog_path, "w"); } @@@ -540,11 -540,11 +540,11 @@@ static int cmd_reflog_expire(int argc, free(collected.e); } - while (i < argc) { - const char *ref = argv[i++]; + for (; i < argc; i++) { + char *ref; unsigned char sha1[20]; - if (!resolve_ref(ref, sha1, 1, NULL)) { - status |= error("%s points nowhere!", ref); + if (!dwim_log(argv[i], strlen(argv[i]), sha1, &ref)) { + status |= error("%s points nowhere!", argv[i]); continue; } set_reflog_expiry_param(&cb, explicit_expiry, ref); diff --combined builtin-revert.c index 472554019a,5c4ab58f46..7e50c2aa54 --- a/builtin-revert.c +++ b/builtin-revert.c @@@ -11,8 -11,6 +11,8 @@@ #include "cache-tree.h" #include "diff.h" #include "revision.h" +#include "rerere.h" +#include "merge-recursive.h" /* * This implements the builtins revert and cherry-pick. @@@ -202,6 -200,36 +202,6 @@@ static void set_author_ident_env(const sha1_to_hex(commit->object.sha1)); } -static int merge_recursive(const char *base_sha1, - const char *head_sha1, const char *head_name, - const char *next_sha1, const char *next_name) -{ - char buffer[256]; - const char *argv[6]; - int i = 0; - - sprintf(buffer, "GITHEAD_%s", head_sha1); - setenv(buffer, head_name, 1); - sprintf(buffer, "GITHEAD_%s", next_sha1); - setenv(buffer, next_name, 1); - - /* - * This three way merge is an interesting one. We are at - * $head, and would want to apply the change between $commit - * and $prev on top of us (when reverting), or the change between - * $prev and $commit on top of us (when cherry-picking or replaying). - */ - argv[i++] = "merge-recursive"; - if (base_sha1) - argv[i++] = base_sha1; - argv[i++] = "--"; - argv[i++] = head_sha1; - argv[i++] = next_sha1; - argv[i++] = NULL; - - return run_command_v_opt(argv, RUN_COMMAND_NO_STDIN | RUN_GIT_CMD); -} - static char *help_msg(const unsigned char *sha1) { static char helpbuf[1024]; @@@ -234,27 -262,14 +234,27 @@@ static int index_is_dirty(void return !!DIFF_OPT_TST(&rev.diffopt, HAS_CHANGES); } +static struct tree *empty_tree(void) +{ + struct tree *tree = xcalloc(1, sizeof(struct tree)); + + tree->object.parsed = 1; + tree->object.type = OBJ_TREE; + pretend_sha1_file(NULL, 0, OBJ_TREE, tree->object.sha1); + return tree; +} + static int revert_or_cherry_pick(int argc, const char **argv) { unsigned char head[20]; struct commit *base, *next, *parent; - int i; + int i, index_fd, clean; char *oneline, *reencoded_message = NULL; const char *message, *encoding; - const char *defmsg = xstrdup(git_path("MERGE_MSG")); + const char *defmsg = git_pathdup("MERGE_MSG"); + struct merge_options o; + struct tree *result, *next_tree, *base_tree, *head_tree; + static struct lock_file index_lock; git_config(git_default_config, NULL); me = action == REVERT ? "revert" : "cherry-pick"; @@@ -265,8 -280,6 +265,8 @@@ if (action == REVERT && !no_replay) die("revert is incompatible with replay"); + if (read_cache() < 0) + die("git %s: failed to read the index", me); if (no_commit) { /* * We do not intend to commit immediately. We just want to @@@ -279,12 -292,12 +279,12 @@@ } else { if (get_sha1("HEAD", head)) die ("You do not have a valid HEAD"); - if (read_cache() < 0) - die("could not read the index"); if (index_is_dirty()) die ("Dirty index: cannot %s", me); - discard_cache(); } + discard_cache(); + + index_fd = hold_locked_index(&index_lock, 1); if (!commit->parents) { if (action == REVERT) @@@ -318,10 -331,6 +318,10 @@@ die ("Cannot get commit message for %s", sha1_to_hex(commit->object.sha1)); + if (parent && parse_commit(parent) < 0) + die("%s: cannot parse parent commit %s", + me, sha1_to_hex(parent->object.sha1)); + /* * "commit" is an existing commit. We would want to apply * the difference it introduces since its first parent "prev" @@@ -329,8 -338,7 +329,8 @@@ * reverse of it if we are revert. */ - msg_fd = hold_lock_file_for_update(&msg_file, defmsg, 1); + msg_fd = hold_lock_file_for_update(&msg_file, defmsg, + LOCK_DIE_ON_ERROR); encoding = get_encoding(message); if (!encoding) @@@ -365,26 -373,13 +365,26 @@@ } } - if (merge_recursive(base == NULL ? - NULL : sha1_to_hex(base->object.sha1), - sha1_to_hex(head), "HEAD", - sha1_to_hex(next->object.sha1), oneline) || - write_cache_as_tree(head, 0, NULL)) { + read_cache(); + init_merge_options(&o); + o.branch1 = "HEAD"; + o.branch2 = oneline; + + head_tree = parse_tree_indirect(head); + next_tree = next ? next->tree : empty_tree(); + base_tree = base ? base->tree : empty_tree(); + + clean = merge_trees(&o, + head_tree, + next_tree, base_tree, &result); + + if (active_cache_changed && + (write_cache(index_fd, active_cache, active_nr) || + commit_locked_index(&index_lock))) + die("%s: Unable to write new index file", me); + + if (!clean) { add_to_msg("\nConflicts:\n\n"); - read_cache(); for (i = 0; i < active_nr;) { struct cache_entry *ce = active_cache[i++]; if (ce_stage(ce)) { @@@ -400,7 -395,6 +400,7 @@@ die ("Error wrapping up %s", defmsg); fprintf(stderr, "Automatic %s failed.%s\n", me, help_msg(commit->object.sha1)); + rerere(); exit(1); } if (commit_lock_file(&msg_file) < 0) diff --combined builtin-tag.c index b13fa34d8c,6c6c35176e..efd77231ff --- a/builtin-tag.c +++ b/builtin-tag.c @@@ -283,7 -283,7 +283,7 @@@ static void create_tag(const unsigned c int fd; /* write the template message before editing: */ - path = xstrdup(git_path("TAG_EDITMSG")); + path = git_pathdup("TAG_EDITMSG"); fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600); if (fd < 0) die("could not create file '%s': %s", @@@ -338,7 -338,7 +338,7 @@@ static int parse_msg_arg(const struct o int cmd_tag(int argc, const char **argv, const char *prefix) { - struct strbuf buf; + struct strbuf buf = STRBUF_INIT; unsigned char object[20], prev[20]; char ref[PATH_MAX]; const char *object_ref, *tag; @@@ -388,6 -388,7 +388,6 @@@ if (verify) return for_each_tag_name(argv, verify_tag); - strbuf_init(&buf, 0); if (msg.given || msgfile) { if (msg.given && msgfile) die("only one -F or -m option is allowed."); diff --combined cache.h index 629cdf3971,eaacd6dd9f..24d0d44f77 --- a/cache.h +++ b/cache.h @@@ -6,14 -6,8 +6,14 @@@ #include "hash.h" #include SHA1_HEADER -#include +#ifndef git_SHA_CTX +#define git_SHA_CTX SHA_CTX +#define git_SHA1_Init SHA1_Init +#define git_SHA1_Update SHA1_Update +#define git_SHA1_Final SHA1_Final +#endif +#include #if defined(NO_DEFLATE_BOUND) || ZLIB_VERNUM < 0x1200 #define deflateBound(c,s) ((s) + (((s) + 7) >> 3) + (((s) + 63) >> 6) + 11) #endif @@@ -132,7 -126,6 +132,7 @@@ struct cache_entry #define CE_NAMEMASK (0x0fff) #define CE_STAGEMASK (0x3000) +#define CE_EXTENDED (0x4000) #define CE_VALID (0x8000) #define CE_STAGESHIFT 12 @@@ -277,7 -270,6 +277,7 @@@ static inline void remove_name_hash(str #define ce_match_stat(ce, st, options) ie_match_stat(&the_index, (ce), (st), (options)) #define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options)) #define cache_name_exists(name, namelen, igncase) index_name_exists(&the_index, (name), (namelen), (igncase)) +#define cache_name_is_other(name, namelen) index_name_is_other(&the_index, (name), (namelen)) #endif enum object_type { @@@ -320,7 -312,6 +320,7 @@@ extern int is_bare_repository(void) extern int is_inside_git_dir(void); extern char *git_work_tree_cfg; extern int is_inside_work_tree(void); +extern int have_git_dir(void); extern const char *get_git_dir(void); extern char *get_object_directory(void); extern char *get_index_file(void); @@@ -379,7 -370,6 +379,7 @@@ extern int index_name_pos(const struct #define ADD_CACHE_OK_TO_REPLACE 2 /* Ok to replace file/directory */ #define ADD_CACHE_SKIP_DFCHECK 4 /* Ok to skip DF conflict checks */ #define ADD_CACHE_JUST_APPEND 8 /* Append only; tree.c::read_tree() */ +#define ADD_CACHE_NEW_ONLY 16 /* Do not replace existing ones */ extern int add_index_entry(struct index_state *, struct cache_entry *ce, int option); extern struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really); extern void rename_index_entry_at(struct index_state *, int pos, const char *new_name); @@@ -388,13 -378,10 +388,13 @@@ extern int remove_file_from_index(struc #define ADD_CACHE_VERBOSE 1 #define ADD_CACHE_PRETEND 2 #define ADD_CACHE_IGNORE_ERRORS 4 +#define ADD_CACHE_IGNORE_REMOVAL 8 +#define ADD_CACHE_INTENT 16 extern int add_to_index(struct index_state *, const char *path, struct stat *, int flags); extern int add_file_to_index(struct index_state *, const char *path, int flags); extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, int refresh); extern int ce_same_name(struct cache_entry *a, struct cache_entry *b); +extern int index_name_is_other(const struct index_state *, const char *, int); /* do stat comparison even if CE_VALID is true */ #define CE_MATCH_IGNORE_VALID 01 @@@ -405,6 -392,7 +405,6 @@@ extern int ie_modified(const struct ind extern int ce_path_match(const struct cache_entry *ce, const char **pathspec); extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, enum object_type type, const char *path); -extern int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object); extern int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object); extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st); @@@ -423,8 -411,6 +423,8 @@@ struct lock_file char on_list; char filename[PATH_MAX]; }; +#define LOCK_DIE_ON_ERROR 1 +#define LOCK_NODEREF 2 extern int hold_lock_file_for_update(struct lock_file *, const char *path, int); extern int hold_lock_file_for_append(struct lock_file *, const char *path, int); extern int commit_lock_file(struct lock_file *); @@@ -466,7 -452,6 +466,7 @@@ enum safe_crlf extern enum safe_crlf safe_crlf; enum branch_track { + BRANCH_TRACK_UNSPECIFIED = -1, BRANCH_TRACK_NEVER = 0, BRANCH_TRACK_REMOTE, BRANCH_TRACK_ALWAYS, @@@ -497,6 -482,10 +497,10 @@@ extern int check_repository_format(void extern char *mksnpath(char *buf, size_t n, const char *fmt, ...) __attribute__((format (printf, 3, 4))); + extern char *git_snpath(char *buf, size_t n, const char *fmt, ...) + __attribute__((format (printf, 3, 4))); + extern char *git_pathdup(const char *fmt, ...) + __attribute__((format (printf, 1, 2))); /* Return a statically allocated filename matching the sha1 signature */ extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2))); @@@ -522,7 -511,6 +526,7 @@@ static inline void hashclr(unsigned cha { memset(hash, 0, 20); } +extern int is_empty_blob_sha1(const unsigned char *sha1); int git_mkstemp(char *path, size_t n, const char *template); @@@ -550,7 -538,6 +554,7 @@@ static inline int is_absolute_path(cons { return path[0] == '/' || has_dos_drive_prefix(path); } +int is_directory(const char *); const char *make_absolute_path(const char *path); const char *make_nonrelative_path(const char *path); const char *make_relative_path(const char *abs, const char *base); @@@ -658,8 -645,6 +662,8 @@@ extern struct alternate_object_databas } *alt_odb_list; extern void prepare_alt_odb(void); extern void add_to_alternates_file(const char *reference); +typedef int alt_odb_fn(struct alternate_object_database *, void *); +extern void foreach_alt_odb(alt_odb_fn, void*); struct pack_window { struct pack_window *next; @@@ -728,11 -713,7 +732,11 @@@ extern struct child_process *git_connec extern int finish_connect(struct child_process *conn); extern int path_match(const char *path, int nr, char **match); extern int get_ack(int fd, unsigned char *result_sha1); -extern struct ref **get_remote_heads(int in, struct ref **list, int nr_match, char **match, unsigned int flags); +struct extra_have_objects { + int nr, alloc; + unsigned char (*array)[20]; +}; +extern struct ref **get_remote_heads(int in, struct ref **list, int nr_match, char **match, unsigned int flags, struct extra_have_objects *); extern int server_supports(const char *feature); extern struct packed_git *parse_pack_index(unsigned char *sha1); @@@ -766,6 -747,7 +770,6 @@@ typedef int (*config_fn_t)(const char * extern int git_default_config(const char *, const char *, void *); extern int git_config_from_file(config_fn_t fn, const char *, void *); extern int git_config(config_fn_t fn, void *); -extern int git_parse_long(const char *, long *); extern int git_parse_ulong(const char *, unsigned long *); extern int git_config_int(const char *, const char *); extern unsigned long git_config_ulong(const char *, const char *); diff --combined config.c index b8d289d217,82807c83b2..67cc1dcad0 --- a/config.c +++ b/config.c @@@ -205,27 -205,8 +205,27 @@@ static int git_parse_file(config_fn_t f int baselen = 0; static char var[MAXNAME]; + /* U+FEFF Byte Order Mark in UTF8 */ + static const unsigned char *utf8_bom = (unsigned char *) "\xef\xbb\xbf"; + const unsigned char *bomptr = utf8_bom; + for (;;) { int c = get_next_char(); + if (bomptr && *bomptr) { + /* We are at the file beginning; skip UTF8-encoded BOM + * if present. Sane editors won't put this in on their + * own, but e.g. Windows Notepad will do it happily. */ + if ((unsigned char) c == *bomptr) { + bomptr++; + continue; + } else { + /* Do not tolerate partial BOM. */ + if (bomptr != utf8_bom) + break; + /* No BOM at file beginning. Cool. */ + bomptr = NULL; + } + } if (c == '\n') { if (config_file_eof) return 0; @@@ -274,7 -255,7 +274,7 @@@ static int parse_unit_factor(const cha return 0; } -int git_parse_long(const char *value, long *ret) +static int git_parse_long(const char *value, long *ret) { if (value && *value) { char *end; @@@ -310,7 -291,7 +310,7 @@@ static void die_bad_config(const char * int git_config_int(const char *name, const char *value) { - long ret; + long ret = 0; if (!git_parse_long(value, &ret)) die_bad_config(name); return ret; @@@ -649,7 -630,7 +649,7 @@@ int git_config(config_fn_t fn, void *da free(user_config); } - repo_config = xstrdup(git_path("config")); + repo_config = git_pathdup("config"); ret += git_config_from_file(fn, repo_config, data); free(repo_config); return ret; @@@ -753,8 -734,9 +753,8 @@@ static int store_write_section(int fd, { const char *dot; int i, success; - struct strbuf sb; + struct strbuf sb = STRBUF_INIT; - strbuf_init(&sb, 0); dot = memchr(key, '.', store.baselen); if (dot) { strbuf_addf(&sb, "[%.*s \"", (int)(dot - key), key); @@@ -779,7 -761,7 +779,7 @@@ static int store_write_pair(int fd, con int i, success; int length = strlen(key + store.baselen + 1); const char *quote = ""; - struct strbuf sb; + struct strbuf sb = STRBUF_INIT; /* * Check to see if the value needs to be surrounded with a dq pair. @@@ -796,6 -778,7 +796,6 @@@ if (i && value[i - 1] == ' ') quote = "\""; - strbuf_init(&sb, 0); strbuf_addf(&sb, "\t%.*s = %s", length, key + store.baselen + 1, quote); @@@ -889,7 -872,7 +889,7 @@@ int git_config_set_multivar(const char if (config_exclusive_filename) config_filename = xstrdup(config_exclusive_filename); else - config_filename = xstrdup(git_path("config")); + config_filename = git_pathdup("config"); /* * Since "key" actually contains the section name and the real @@@ -1149,7 -1132,7 +1149,7 @@@ int git_config_rename_section(const cha if (config_exclusive_filename) config_filename = xstrdup(config_exclusive_filename); else - config_filename = xstrdup(git_path("config")); + config_filename = git_pathdup("config"); out_fd = hold_lock_file_for_update(lock, config_filename, 0); if (out_fd < 0) { ret = error("could not lock config file %s", config_filename); diff --combined environment.c index 0693cd9a42,df4f03a95f..bf93a598d0 --- a/environment.c +++ b/environment.c @@@ -71,7 -71,7 +71,7 @@@ static void setup_git_env(void } git_graft_file = getenv(GRAFT_ENVIRONMENT); if (!git_graft_file) - git_graft_file = xstrdup(git_path("info/grafts")); + git_graft_file = git_pathdup("info/grafts"); } int is_bare_repository(void) @@@ -80,11 -80,6 +80,11 @@@ return is_bare_repository_cfg && !get_git_work_tree(); } +int have_git_dir(void) +{ + return !!git_dir; +} + const char *get_git_dir(void) { if (!git_dir) diff --combined refs.c index 0a126fa371,d589b25562..01e4df4ccf --- a/refs.c +++ b/refs.c @@@ -390,18 -390,6 +390,18 @@@ int resolve_gitlink_ref(const char *pat return retval; } +/* + * If the "reading" argument is set, this function finds out what _object_ + * the ref points at by "reading" the ref. The ref, if it is not symbolic, + * has to exist, and if it is symbolic, it has to point at an existing ref, + * because the "read" goes through the symref to the ref it points at. + * + * The access that is not "reading" may often be "writing", but does not + * have to; it can be merely checking _where it leads to_. If it is a + * prelude to "writing" to the ref, a write to a symref that points at + * yet-to-be-born ref will create the real ref pointed by the symref. + * reading=0 allows the caller to check where such a symref leads to. + */ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *flag) { int depth = MAXDEPTH; @@@ -413,7 -401,7 +413,7 @@@ *flag = 0; for (;;) { - const char *path = git_path("%s", ref); + char path[PATH_MAX]; struct stat st; char *buf; int fd; @@@ -421,7 -409,14 +421,8 @@@ if (--depth < 0) return NULL; + git_snpath(path, sizeof(path), "%s", ref); - /* Special case: non-existing file. - * Not having the refs/heads/new-branch is OK - * if we are writing into it, so is .git/HEAD - * that points at refs/heads/master still to be - * born. It is NOT OK if we are resolving for - * reading. - */ + /* Special case: non-existing file. */ if (lstat(path, &st) < 0) { struct ref_list *list = get_packed_refs(); while (list) { @@@ -796,7 -791,7 +797,7 @@@ static struct ref_lock *lock_ref_sha1_b struct ref_lock *lock; struct stat st; int last_errno = 0; - int type; + int type, lflags; int mustexist = (old_sha1 && !is_null_sha1(old_sha1)); lock = xcalloc(1, sizeof(struct ref_lock)); @@@ -836,11 -831,8 +837,11 @@@ lock->lk = xcalloc(1, sizeof(struct lock_file)); - if (flags & REF_NODEREF) + lflags = LOCK_DIE_ON_ERROR; + if (flags & REF_NODEREF) { ref = orig_ref; + lflags |= LOCK_NODEREF; + } lock->ref_name = xstrdup(ref); lock->orig_ref_name = xstrdup(orig_ref); ref_file = git_path("%s", ref); @@@ -854,8 -846,8 +855,8 @@@ error("unable to create directory for %s", ref_file); goto error_return; } - lock->lock_fd = hold_lock_file_for_update(lock->lk, ref_file, 1); + lock->lock_fd = hold_lock_file_for_update(lock->lk, ref_file, lflags); return old_sha1 ? verify_lock(lock, old_sha1, mustexist) : lock; error_return: @@@ -1130,13 -1122,14 +1131,14 @@@ static int log_ref_write(const char *re int logfd, written, oflags = O_APPEND | O_WRONLY; unsigned maxlen, len; int msglen; - char *log_file, *logrec; + char log_file[PATH_MAX]; + char *logrec; const char *committer; if (log_all_ref_updates < 0) log_all_ref_updates = !is_bare_repository(); - log_file = git_path("logs/%s", ref_name); + git_snpath(log_file, sizeof(log_file), "logs/%s", ref_name); if (log_all_ref_updates && (!prefixcmp(ref_name, "refs/heads/") || @@@ -1265,7 -1258,7 +1267,7 @@@ int create_symref(const char *ref_targe const char *lockpath; char ref[1000]; int fd, len, written; - char *git_HEAD = xstrdup(git_path("%s", ref_target)); + char *git_HEAD = git_pathdup("%s", ref_target); unsigned char old_sha1[20], new_sha1[20]; if (logmsg && read_ref(ref_target, old_sha1)) diff --combined rerere.c index 8e5532b1ff,3d6ee8fa2a..02931a151f --- a/rerere.c +++ b/rerere.c @@@ -73,13 -73,10 +73,13 @@@ static int write_rr(struct string_list static int handle_file(const char *path, unsigned char *sha1, const char *output) { - SHA_CTX ctx; + git_SHA_CTX ctx; char buf[1024]; - int hunk = 0, hunk_no = 0; - struct strbuf one, two; + int hunk_no = 0; + enum { + RR_CONTEXT = 0, RR_SIDE_1, RR_SIDE_2, RR_ORIGINAL, + } hunk = RR_CONTEXT; + struct strbuf one = STRBUF_INIT, two = STRBUF_INIT; FILE *f = fopen(path, "r"); FILE *out = NULL; @@@ -95,28 -92,26 +95,28 @@@ } if (sha1) - SHA1_Init(&ctx); + git_SHA1_Init(&ctx); - strbuf_init(&one, 0); - strbuf_init(&two, 0); while (fgets(buf, sizeof(buf), f)) { if (!prefixcmp(buf, "<<<<<<< ")) { - if (hunk) + if (hunk != RR_CONTEXT) goto bad; - hunk = 1; + hunk = RR_SIDE_1; + } else if (!prefixcmp(buf, "|||||||") && isspace(buf[7])) { + if (hunk != RR_SIDE_1) + goto bad; + hunk = RR_ORIGINAL; } else if (!prefixcmp(buf, "=======") && isspace(buf[7])) { - if (hunk != 1) + if (hunk != RR_SIDE_1 && hunk != RR_ORIGINAL) goto bad; - hunk = 2; + hunk = RR_SIDE_2; } else if (!prefixcmp(buf, ">>>>>>> ")) { - if (hunk != 2) + if (hunk != RR_SIDE_2) goto bad; if (strbuf_cmp(&one, &two) > 0) strbuf_swap(&one, &two); hunk_no++; - hunk = 0; + hunk = RR_CONTEXT; if (out) { fputs("<<<<<<<\n", out); fwrite(one.buf, one.len, 1, out); @@@ -125,18 -120,16 +125,18 @@@ fputs(">>>>>>>\n", out); } if (sha1) { - SHA1_Update(&ctx, one.buf ? one.buf : "", + git_SHA1_Update(&ctx, one.buf ? one.buf : "", one.len + 1); - SHA1_Update(&ctx, two.buf ? two.buf : "", + git_SHA1_Update(&ctx, two.buf ? two.buf : "", two.len + 1); } strbuf_reset(&one); strbuf_reset(&two); - } else if (hunk == 1) + } else if (hunk == RR_SIDE_1) strbuf_addstr(&one, buf); - else if (hunk == 2) + else if (hunk == RR_ORIGINAL) + ; /* discard */ + else if (hunk == RR_SIDE_2) strbuf_addstr(&two, buf); else if (out) fputs(buf, out); @@@ -152,8 -145,8 +152,8 @@@ if (out) fclose(out); if (sha1) - SHA1_Final(sha1, &ctx); - if (hunk) { + git_SHA1_Final(sha1, &ctx); + if (hunk != RR_CONTEXT) { if (output) unlink(output); return error("Could not parse conflict hunks in %s", path); @@@ -326,6 -319,7 +326,6 @@@ static int git_rerere_config(const cha static int is_rerere_enabled(void) { - struct stat st; const char *rr_cache; int rr_cache_exists; @@@ -333,7 -327,7 +333,7 @@@ return 0; rr_cache = git_path("rr-cache"); - rr_cache_exists = !stat(rr_cache, &st) && S_ISDIR(st.st_mode); + rr_cache_exists = is_directory(rr_cache); if (rerere_enabled < 0) return rr_cache_exists; @@@ -351,9 -345,8 +351,9 @@@ int setup_rerere(struct string_list *me if (!is_rerere_enabled()) return -1; - merge_rr_path = xstrdup(git_path("MERGE_RR")); + merge_rr_path = git_pathdup("MERGE_RR"); - fd = hold_lock_file_for_update(&write_lock, merge_rr_path, 1); + fd = hold_lock_file_for_update(&write_lock, merge_rr_path, + LOCK_DIE_ON_ERROR); read_rr(merge_rr); return fd; }