commit_locked_index(), when writing to an alternate index file, duplicates (poorly) the code in commit_lock_file(). And anyway, it shouldn't have to know so much about the internal workings of lockfile objects. So extract a new function commit_lock_file_to() that does the work common to the two functions, and call it from both commit_lock_file() and commit_locked_index(). Signed-off-by: Michael Haggerty <mhagger@xxxxxxxxxxxx> --- Documentation/technical/api-lockfile.txt | 14 ++++++++---- cache.h | 1 + lockfile.c | 39 +++++++++++++++++++++----------- read-cache.c | 13 +++-------- 4 files changed, 40 insertions(+), 27 deletions(-) diff --git a/Documentation/technical/api-lockfile.txt b/Documentation/technical/api-lockfile.txt index 2514559..3ee4299 100644 --- a/Documentation/technical/api-lockfile.txt +++ b/Documentation/technical/api-lockfile.txt @@ -73,6 +73,12 @@ commit_lock_file:: `commit_lock_file()` for a `lock_file` object that is not currently locked. +commit_lock_file_to:: + + Like `commit_lock_file()`, except that it takes an explicit + `path` argument to which the lockfile should be renamed. The + `path` must be on the same filesystem as the lock file. + rollback_lock_file:: Take a pointer to the `struct lock_file` initialized @@ -91,10 +97,10 @@ Because the structure is used in an `atexit(3)` handler, its storage has to stay throughout the life of the program. It cannot be an auto variable allocated on the stack. -Call `commit_lock_file()` or `rollback_lock_file()` when you are -done writing to the file descriptor. If you do not call either -and simply `exit(3)` from the program, an `atexit(3)` handler -will close and remove the lockfile. +Call `commit_lock_file()`, `commit_lock_file_to()`, or +`rollback_lock_file()` when you are done writing to the file +descriptor. If you do not call either and simply `exit(3)` from the +program, an `atexit(3)` handler will close and remove the lockfile. If you need to close the file descriptor you obtained from `hold_lock_file_for_update` function yourself, do so by calling diff --git a/cache.h b/cache.h index 307cc8e..45688d5 100644 --- a/cache.h +++ b/cache.h @@ -590,6 +590,7 @@ extern void unable_to_lock_message(const char *path, int err, extern NORETURN void unable_to_lock_die(const char *path, int err); 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_to(struct lock_file *, const char *path); extern int commit_lock_file(struct lock_file *); extern int reopen_lock_file(struct lock_file *); extern void update_index_if_able(struct index_state *, struct lock_file *); diff --git a/lockfile.c b/lockfile.c index 3d5ab4f..480c2ba 100644 --- a/lockfile.c +++ b/lockfile.c @@ -58,8 +58,9 @@ * - Locked, lockfile closed (after close_lock_file()). Same as the * previous state, except that the lockfile is closed and fd is -1. * - * - Unlocked (after commit_lock_file(), rollback_lock_file(), or a - * failed attempt to lock). In this state: + * - Unlocked (after commit_lock_file(), commit_lock_file_to(), + * rollback_lock_file(), or a failed attempt to lock). In this + * state: * - active is unset * - filename is empty (usually, though there are transitory * states in which this condition doesn't hold) @@ -290,24 +291,16 @@ int reopen_lock_file(struct lock_file *lk) return lk->fd; } -int commit_lock_file(struct lock_file *lk) +int commit_lock_file_to(struct lock_file *lk, const char *path) { - static struct strbuf result_file = STRBUF_INIT; int save_errno; - int err; if (!lk->active) - die("BUG: attempt to commit unlocked object"); + die("BUG: attempt to commit unlocked object to \"%s\"", path); if (lk->fd >= 0 && close_lock_file(lk)) goto rollback; - - /* remove ".lock": */ - strbuf_add(&result_file, lk->filename.buf, - lk->filename.len - LOCK_SUFFIX_LEN); - err = rename(lk->filename.buf, result_file.buf); - strbuf_reset(&result_file); - if (err) + if (rename(lk->filename.buf, path)) goto rollback; lk->active = 0; strbuf_reset(&lk->filename); @@ -320,6 +313,26 @@ rollback: return -1; } +int commit_lock_file(struct lock_file *lk) +{ + static struct strbuf result_file = STRBUF_INIT; + int err; + + if (!lk->active) + die("BUG: attempt to commit unlocked object"); + + if (lk->filename.len <= LOCK_SUFFIX_LEN || + strcmp(lk->filename.buf + lk->filename.len - LOCK_SUFFIX_LEN, LOCK_SUFFIX)) + die("BUG: lockfile filename corrupt"); + + /* remove ".lock": */ + strbuf_add(&result_file, lk->filename.buf, + lk->filename.len - LOCK_SUFFIX_LEN); + err = commit_lock_file_to(lk, result_file.buf); + strbuf_reset(&result_file); + return err; +} + int hold_locked_index(struct lock_file *lk, int die_on_error) { return hold_lock_file_for_update(lk, get_index_file(), diff --git a/read-cache.c b/read-cache.c index c126916..f3eb5e9 100644 --- a/read-cache.c +++ b/read-cache.c @@ -2023,17 +2023,10 @@ void set_alternate_index_output(const char *name) static int commit_locked_index(struct lock_file *lk) { - if (alternate_index_output) { - if (lk->fd >= 0 && close_lock_file(lk)) - return -1; - if (rename(lk->filename.buf, alternate_index_output)) - return -1; - lk->active = 0; - strbuf_reset(&lk->filename); - return 0; - } else { + if (alternate_index_output) + return commit_lock_file_to(lk, alternate_index_output); + else return commit_lock_file(lk); - } } static int do_write_locked_index(struct index_state *istate, struct lock_file *lock, -- 2.1.0 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html