diff options
author | Vicent Marti <vicent@github.com> | 2013-12-18 09:33:45 -0800 |
---|---|---|
committer | Vicent Marti <vicent@github.com> | 2013-12-18 09:33:45 -0800 |
commit | 4e1f517c61fef323b9cb3acedd19ce7859a8e546 (patch) | |
tree | 87823d6c36e00b3098069142ba9e630e2570f1b7 /src | |
parent | a7ecd1a9e36df5d6843c1863542c02d777e9e8b5 (diff) | |
parent | f21051297cc698644ea0dc9c7122ec944dba2863 (diff) | |
download | libgit2-4e1f517c61fef323b9cb3acedd19ce7859a8e546.tar.gz |
Merge pull request #1920 from libgit2/cmn/ref-with-log
Reference operations with log
Diffstat (limited to 'src')
-rw-r--r-- | src/refdb.c | 24 | ||||
-rw-r--r-- | src/refdb.h | 10 | ||||
-rw-r--r-- | src/refdb_fs.c | 217 | ||||
-rw-r--r-- | src/reflog.c | 19 | ||||
-rw-r--r-- | src/refs.c | 213 | ||||
-rw-r--r-- | src/refs.h | 1 | ||||
-rw-r--r-- | src/stash.c | 24 |
7 files changed, 387 insertions, 121 deletions
diff --git a/src/refdb.c b/src/refdb.c index adb58806e..411423d57 100644 --- a/src/refdb.c +++ b/src/refdb.c @@ -167,14 +167,14 @@ void git_refdb_iterator_free(git_reference_iterator *iter) iter->free(iter); } -int git_refdb_write(git_refdb *db, git_reference *ref, int force) +int git_refdb_write(git_refdb *db, git_reference *ref, int force, const git_signature *who, const char *message) { assert(db && db->backend); GIT_REFCOUNT_INC(db); ref->db = db; - return db->backend->write(db->backend, ref, force); + return db->backend->write(db->backend, ref, force, who, message); } int git_refdb_rename( @@ -182,12 +182,14 @@ int git_refdb_rename( git_refdb *db, const char *old_name, const char *new_name, - int force) + int force, + const git_signature *who, + const char *message) { int error; assert(db && db->backend); - error = db->backend->rename(out, db->backend, old_name, new_name, force); + error = db->backend->rename(out, db->backend, old_name, new_name, force, who, message); if (error < 0) return error; @@ -219,3 +221,17 @@ int git_refdb_reflog_read(git_reflog **out, git_refdb *db, const char *name) return 0; } + +int git_refdb_has_log(git_refdb *db, const char *refname) +{ + assert(db && refname); + + return db->backend->has_log(db->backend, refname); +} + +int git_refdb_ensure_log(git_refdb *db, const char *refname) +{ + assert(db && refname); + + return db->backend->ensure_log(db->backend, refname); +} diff --git a/src/refdb.h b/src/refdb.h index 0ee60d911..91eecb782 100644 --- a/src/refdb.h +++ b/src/refdb.h @@ -33,18 +33,24 @@ int git_refdb_rename( git_refdb *db, const char *old_name, const char *new_name, - int force); + int force, + const git_signature *who, + const char *message); int git_refdb_iterator(git_reference_iterator **out, git_refdb *db, const char *glob); int git_refdb_iterator_next(git_reference **out, git_reference_iterator *iter); int git_refdb_iterator_next_name(const char **out, git_reference_iterator *iter); void git_refdb_iterator_free(git_reference_iterator *iter); -int git_refdb_write(git_refdb *refdb, git_reference *ref, int force); +int git_refdb_write(git_refdb *refdb, git_reference *ref, int force, const git_signature *who, const char *message); int git_refdb_delete(git_refdb *refdb, const char *ref_name); int git_refdb_reflog_read(git_reflog **out, git_refdb *db, const char *name); int git_refdb_reflog_write(git_reflog *reflog); +int git_refdb_has_log(git_refdb *db, const char *refname); +int git_refdb_ensure_log(git_refdb *refdb, const char *refname); + + #endif diff --git a/src/refdb_fs.c b/src/refdb_fs.c index df7cb9d4d..53c42458f 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -688,9 +688,8 @@ static int reference_path_available( return 0; } -static int loose_write(refdb_fs_backend *backend, const git_reference *ref) +static int loose_lock(git_filebuf *file, refdb_fs_backend *backend, const git_reference *ref) { - git_filebuf file = GIT_FILEBUF_INIT; git_buf ref_path = GIT_BUF_INIT; /* Remove a possibly existing empty directory hierarchy @@ -702,25 +701,29 @@ static int loose_write(refdb_fs_backend *backend, const git_reference *ref) if (git_buf_joinpath(&ref_path, backend->path, ref->name) < 0) return -1; - if (git_filebuf_open(&file, ref_path.ptr, GIT_FILEBUF_FORCE, GIT_REFS_FILE_MODE) < 0) { + if (git_filebuf_open(file, ref_path.ptr, GIT_FILEBUF_FORCE, GIT_REFS_FILE_MODE) < 0) { git_buf_free(&ref_path); return -1; } git_buf_free(&ref_path); + return 0; +} +static int loose_commit(git_filebuf *file, const git_reference *ref) +{ if (ref->type == GIT_REF_OID) { char oid[GIT_OID_HEXSZ + 1]; git_oid_nfmt(oid, sizeof(oid), &ref->target.oid); - git_filebuf_printf(&file, "%s\n", oid); + git_filebuf_printf(file, "%s\n", oid); } else if (ref->type == GIT_REF_SYMBOLIC) { - git_filebuf_printf(&file, GIT_SYMREF "%s\n", ref->target.symbolic); + git_filebuf_printf(file, GIT_SYMREF "%s\n", ref->target.symbolic); } else { assert(0); /* don't let this happen */ } - return git_filebuf_commit(&file); + return git_filebuf_commit(file); } /* @@ -907,12 +910,33 @@ fail: return -1; } +static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, const git_signature *author, const char *message); +static int has_reflog(git_repository *repo, const char *name); + +/* We only write if it's under heads/, remotes/ or notes/ or if it already has a log */ +static bool should_write_reflog(git_repository *repo, const char *name) +{ + if (has_reflog(repo, name)) + return 1; + + if (!git__prefixcmp(name, GIT_REFS_HEADS_DIR) || + !git__strcmp(name, GIT_HEAD_FILE) || + !git__prefixcmp(name, GIT_REFS_REMOTES_DIR) || + !git__prefixcmp(name, GIT_REFS_NOTES_DIR)) + return 1; + + return 0; +} + static int refdb_fs_backend__write( git_refdb_backend *_backend, const git_reference *ref, - int force) + int force, + const git_signature *who, + const char *message) { refdb_fs_backend *backend = (refdb_fs_backend *)_backend; + git_filebuf file = GIT_FILEBUF_INIT; int error; assert(backend); @@ -921,7 +945,17 @@ static int refdb_fs_backend__write( if (error < 0) return error; - return loose_write(backend, ref); + /* We need to perform the reflog append under the ref's lock */ + if ((error = loose_lock(&file, backend, ref)) < 0) + return error; + + if (should_write_reflog(backend->repo, ref->name) && + (error = reflog_append(backend, ref, who, message)) < 0) { + git_filebuf_cleanup(&file); + return error; + } + + return loose_commit(&file, ref); } static int refdb_fs_backend__delete( @@ -969,15 +1003,20 @@ static int refdb_fs_backend__delete( return packed_write(backend); } +static int refdb_reflog_fs__rename(git_refdb_backend *_backend, const char *old_name, const char *new_name); + static int refdb_fs_backend__rename( git_reference **out, git_refdb_backend *_backend, const char *old_name, const char *new_name, - int force) + int force, + const git_signature *who, + const char *message) { refdb_fs_backend *backend = (refdb_fs_backend *)_backend; git_reference *old, *new; + git_filebuf file = GIT_FILEBUF_INIT; int error; assert(backend); @@ -998,7 +1037,28 @@ static int refdb_fs_backend__rename( return -1; } - if ((error = loose_write(backend, new)) < 0 || out == NULL) { + if ((error = loose_lock(&file, backend, new)) < 0) { + git_reference_free(new); + return error; + } + + /* Try to rename the refog; it's ok if the old doesn't exist */ + error = refdb_reflog_fs__rename(_backend, old_name, new_name); + if (((error == 0) || (error == GIT_ENOTFOUND)) && + ((error = reflog_append(backend, new, who, message)) < 0)) { + git_reference_free(new); + git_filebuf_cleanup(&file); + return error; + } + + if (error < 0) { + git_reference_free(new); + git_filebuf_cleanup(&file); + return error; + } + + + if ((error = loose_commit(&file, new)) < 0 || out == NULL) { git_reference_free(new); return error; } @@ -1173,7 +1233,7 @@ static int create_new_reflog_file(const char *filepath) return error; if ((fd = p_open(filepath, - O_WRONLY | O_CREAT | O_TRUNC, + O_WRONLY | O_CREAT, GIT_REFLOG_FILE_MODE)) < 0) return -1; @@ -1185,6 +1245,50 @@ GIT_INLINE(int) retrieve_reflog_path(git_buf *path, git_repository *repo, const return git_buf_join_n(path, '/', 3, repo->path_repository, GIT_REFLOG_DIR, name); } +static int refdb_reflog_fs__ensure_log(git_refdb_backend *_backend, const char *name) +{ + refdb_fs_backend *backend; + git_repository *repo; + git_buf path = GIT_BUF_INIT; + int error; + + assert(_backend && name); + + backend = (refdb_fs_backend *) _backend; + repo = backend->repo; + + if ((error = retrieve_reflog_path(&path, repo, name)) < 0) + return error; + + return create_new_reflog_file(git_buf_cstr(&path)); +} + +static int has_reflog(git_repository *repo, const char *name) +{ + int ret = 0; + git_buf path = GIT_BUF_INIT; + + if (retrieve_reflog_path(&path, repo, name) < 0) + goto cleanup; + + ret = git_path_isfile(git_buf_cstr(&path)); + +cleanup: + git_buf_free(&path); + return ret; +} + +static int refdb_reflog_fs__has_log(git_refdb_backend *_backend, const char *name) +{ + refdb_fs_backend *backend; + + assert(_backend && name); + + backend = (refdb_fs_backend *) _backend; + + return has_reflog(backend->repo, name); +} + static int refdb_reflog_fs__read(git_reflog **out, git_refdb_backend *_backend, const char *name) { int error = -1; @@ -1264,34 +1368,48 @@ static int serialize_reflog_entry( return git_buf_oom(buf); } +static int lock_reflog(git_filebuf *file, refdb_fs_backend *backend, const char *refname) +{ + git_repository *repo; + git_buf log_path = GIT_BUF_INIT; + int error; + + repo = backend->repo; + + if (retrieve_reflog_path(&log_path, repo, refname) < 0) + return -1; + + if (!git_path_isfile(git_buf_cstr(&log_path))) { + giterr_set(GITERR_INVALID, + "Log file for reference '%s' doesn't exist.", refname); + error = -1; + goto cleanup; + } + + error = git_filebuf_open(file, git_buf_cstr(&log_path), 0, GIT_REFLOG_FILE_MODE); + +cleanup: + git_buf_free(&log_path); + + return error; +} + static int refdb_reflog_fs__write(git_refdb_backend *_backend, git_reflog *reflog) { int error = -1; unsigned int i; git_reflog_entry *entry; - git_repository *repo; refdb_fs_backend *backend; - git_buf log_path = GIT_BUF_INIT; git_buf log = GIT_BUF_INIT; git_filebuf fbuf = GIT_FILEBUF_INIT; assert(_backend && reflog); backend = (refdb_fs_backend *) _backend; - repo = backend->repo; - if (retrieve_reflog_path(&log_path, repo, reflog->ref_name) < 0) + if ((error = lock_reflog(&fbuf, backend, reflog->ref_name)) < 0) return -1; - if (!git_path_isfile(git_buf_cstr(&log_path))) { - giterr_set(GITERR_INVALID, - "Log file for reference '%s' doesn't exist.", reflog->ref_name); - goto cleanup; - } - - if ((error = git_filebuf_open(&fbuf, git_buf_cstr(&log_path), 0, GIT_REFLOG_FILE_MODE)) < 0) - goto cleanup; - git_vector_foreach(&reflog->entries, i, entry) { if (serialize_reflog_entry(&log, &(entry->oid_old), &(entry->oid_cur), entry->committer, entry->msg) < 0) goto cleanup; @@ -1308,7 +1426,49 @@ cleanup: success: git_buf_free(&log); - git_buf_free(&log_path); + + return error; +} + +/* Append to the reflog, must be called under reference lock */ +static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, const git_signature *who, const char *message) +{ + int error; + git_oid old_id, new_id; + git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT; + git_repository *repo = backend->repo; + + /* Creation of symbolic references doesn't get a reflog entry */ + if (ref->type == GIT_REF_SYMBOLIC) + return 0; + + error = git_reference_name_to_id(&old_id, repo, ref->name); + if (error == GIT_ENOTFOUND) { + memset(&old_id, 0, sizeof(git_oid)); + error = 0; + } + if (error < 0) + return error; + + git_oid_cpy(&new_id, git_reference_target(ref)); + + if ((error = serialize_reflog_entry(&buf, &old_id, &new_id, who, message)) < 0) + goto cleanup; + + if ((error = retrieve_reflog_path(&path, repo, ref->name)) < 0) + goto cleanup; + + if (((error = git_futils_mkpath2file(git_buf_cstr(&path), 0777)) < 0) && + (error != GIT_EEXISTS)) { + goto cleanup; + } + + error = git_futils_writebuffer(&buf, git_buf_cstr(&path), O_WRONLY|O_CREAT|O_APPEND, GIT_REFLOG_FILE_MODE); + +cleanup: + git_buf_free(&buf); + git_buf_free(&path); + return error; } @@ -1340,6 +1500,11 @@ static int refdb_reflog_fs__rename(git_refdb_backend *_backend, const char *old_ if (git_buf_joinpath(&new_path, git_buf_cstr(&temp_path), git_buf_cstr(&normalized)) < 0) return -1; + if (!git_path_exists(git_buf_cstr(&old_path))) { + error = GIT_ENOTFOUND; + goto cleanup; + } + /* * Move the reflog to a temporary place. This two-phase renaming is required * in order to cope with funny renaming use cases when one tries to move a reference @@ -1454,6 +1619,8 @@ int git_refdb_backend_fs( backend->parent.del = &refdb_fs_backend__delete; backend->parent.rename = &refdb_fs_backend__rename; backend->parent.compress = &refdb_fs_backend__compress; + backend->parent.has_log = &refdb_reflog_fs__has_log; + backend->parent.ensure_log = &refdb_reflog_fs__ensure_log; backend->parent.free = &refdb_fs_backend__free; backend->parent.reflog_read = &refdb_reflog_fs__read; backend->parent.reflog_write = &refdb_reflog_fs__write; diff --git a/src/reflog.c b/src/reflog.c index cebb87d86..9b2b201bf 100644 --- a/src/reflog.c +++ b/src/reflog.c @@ -230,22 +230,3 @@ int git_reflog_drop(git_reflog *reflog, size_t idx, int rewrite_previous_entry) return 0; } - -int git_reflog_append_to(git_repository *repo, const char *name, const git_oid *id, - const git_signature *committer, const char *msg) -{ - int error; - git_reflog *reflog; - - if ((error = git_reflog_read(&reflog, repo, name)) < 0) - return error; - - if ((error = git_reflog_append(reflog, id, committer, msg)) < 0) - goto cleanup; - - error = git_reflog_write(reflog); - -cleanup: - git_reflog_free(reflog); - return error; -} diff --git a/src/refs.c b/src/refs.c index 4f3a557c6..83343f41b 100644 --- a/src/refs.c +++ b/src/refs.c @@ -21,6 +21,7 @@ #include <git2/refs.h> #include <git2/refdb.h> #include <git2/sys/refs.h> +#include <git2/signature.h> GIT__USE_STRMAP; @@ -328,13 +329,18 @@ static int reference__create( const char *name, const git_oid *oid, const char *symbolic, - int force) + int force, + const git_signature *signature, + const char *log_message) { char normalized[GIT_REFNAME_MAX]; git_refdb *refdb; git_reference *ref = NULL; int error = 0; + assert(repo && name); + assert(symbolic || signature); + if (ref_out) *ref_out = NULL; @@ -347,15 +353,34 @@ static int reference__create( return error; if (oid != NULL) { + git_odb *odb; + assert(symbolic == NULL); - ref = git_reference__alloc(normalized, oid, NULL); + + /* Sanity check the reference being created - target must exist. */ + if ((error = git_repository_odb__weakptr(&odb, repo)) < 0) + return error; + + if (!git_odb_exists(odb, oid)) { + giterr_set(GITERR_REFERENCE, + "Target OID for the reference doesn't exist on the repository"); + return -1; + } + + ref = git_reference__alloc(name, oid, NULL); } else { - ref = git_reference__alloc_symbolic(normalized, symbolic); + char normalized_target[GIT_REFNAME_MAX]; + + if ((error = git_reference__normalize_name_lax( + normalized_target, sizeof(normalized_target), symbolic)) < 0) + return error; + + ref = git_reference__alloc_symbolic(name, normalized_target); } GITERR_CHECK_ALLOC(ref); - if ((error = git_refdb_write(refdb, ref, force)) < 0) { + if ((error = git_refdb_write(refdb, ref, force, signature, log_message)) < 0) { git_reference_free(ref); return error; } @@ -375,22 +400,37 @@ int git_reference_create( const git_oid *oid, int force) { - git_odb *odb; - int error = 0; + git_signature *who; + int error; - assert(repo && name && oid); + assert(oid); - /* Sanity check the reference being created - target must exist. */ - if ((error = git_repository_odb__weakptr(&odb, repo)) < 0) + /* Should we return an error if there is no default? */ + if (((error = git_signature_default(&who, repo)) < 0) && + ((error = git_signature_now(&who, "unknown", "unknown")) < 0)) { return error; - - if (!git_odb_exists(odb, oid)) { - giterr_set(GITERR_REFERENCE, - "Target OID for the reference doesn't exist on the repository"); - return -1; } - return reference__create(ref_out, repo, name, oid, NULL, force); + error = reference__create(ref_out, repo, name, oid, NULL, force, who, NULL); + + git_signature_free(who); + + return error; +} + +int git_reference_create_with_log( + git_reference **ref_out, + git_repository *repo, + const char *name, + const git_oid *oid, + int force, + const git_signature *signature, + const char *log_message) +{ + assert(oid && signature && log_message); + + return reference__create( + ref_out, repo, name, oid, NULL, force, signature, log_message); } int git_reference_symbolic_create( @@ -400,16 +440,17 @@ int git_reference_symbolic_create( const char *target, int force) { - char normalized[GIT_REFNAME_MAX]; - int error = 0; - - assert(repo && name && target); + assert(target); + return reference__create(ref_out, repo, name, NULL, target, force, NULL, NULL); +} - if ((error = git_reference__normalize_name_lax( - normalized, sizeof(normalized), target)) < 0) - return error; +static int ensure_is_an_updatable_direct_reference(git_reference *ref) +{ + if (ref->type == GIT_REF_OID) + return 0; - return reference__create(ref_out, repo, name, NULL, normalized, force); + giterr_set(GITERR_REFERENCE, "Cannot set OID on symbolic reference"); + return -1; } int git_reference_set_target( @@ -417,43 +458,68 @@ int git_reference_set_target( git_reference *ref, const git_oid *id) { + int error; + assert(out && ref && id); - if (ref->type != GIT_REF_OID) { - giterr_set(GITERR_REFERENCE, "Cannot set OID on symbolic reference"); - return -1; - } + if ((error = ensure_is_an_updatable_direct_reference(ref)) < 0) + return error; return git_reference_create(out, ref->db->repo, ref->name, id, 1); } +int git_reference_set_target_with_log( + git_reference **out, + git_reference *ref, + const git_oid *id, + const git_signature *signature, + const char *log_message) +{ + int error; + + assert(out && ref && id); + assert(signature && log_message); + + if ((error = ensure_is_an_updatable_direct_reference(ref)) < 0) + return error; + + return git_reference_create_with_log( + out, ref->db->repo, ref->name, id, 1, signature, log_message); +} + +static int ensure_is_an_updatable_symbolic_reference(git_reference *ref) +{ + if (ref->type == GIT_REF_SYMBOLIC) + return 0; + + giterr_set(GITERR_REFERENCE, "Cannot set symbolic target on a direct reference"); + return -1; +} + int git_reference_symbolic_set_target( git_reference **out, git_reference *ref, const char *target) { + int error; + assert(out && ref && target); - if (ref->type != GIT_REF_SYMBOLIC) { - giterr_set(GITERR_REFERENCE, - "Cannot set symbolic target on a direct reference"); - return -1; - } + if ((error = ensure_is_an_updatable_symbolic_reference(ref)) < 0) + return error; return git_reference_symbolic_create(out, ref->db->repo, ref->name, target, 1); } -int git_reference_rename( - git_reference **out, - git_reference *ref, - const char *new_name, - int force) +static int reference__rename(git_reference **out, git_reference *ref, const char *new_name, int force, + const git_signature *signature, const char *message) { unsigned int normalization_flags; char normalized[GIT_REFNAME_MAX]; bool should_head_be_updated = false; int error = 0; - int reference_has_log; + + assert(ref && new_name && signature); normalization_flags = ref->type == GIT_REF_SYMBOLIC ? GIT_REF_FORMAT_ALLOW_ONELEVEL : GIT_REF_FORMAT_NORMAL; @@ -462,13 +528,14 @@ int git_reference_rename( normalized, sizeof(normalized), new_name, normalization_flags)) < 0) return error; + /* Check if we have to update HEAD. */ if ((error = git_branch_is_head(ref)) < 0) return error; should_head_be_updated = (error > 0); - if ((error = git_refdb_rename(out, ref->db, ref->name, new_name, force)) < 0) + if ((error = git_refdb_rename(out, ref->db, ref->name, new_name, force, signature, message)) < 0) return error; /* Update HEAD it was pointing to the reference being renamed */ @@ -478,15 +545,41 @@ int git_reference_rename( return error; } - /* Rename the reflog file, if it exists. */ - reference_has_log = git_reference_has_log(ref); - if (reference_has_log < 0) - return reference_has_log; + return 0; +} + + +int git_reference_rename( + git_reference **out, + git_reference *ref, + const char *new_name, + int force) +{ + git_signature *who; + int error; - if (reference_has_log && (error = git_reflog_rename(git_reference_owner(ref), git_reference_name(ref), new_name)) < 0) + /* Should we return an error if there is no default? */ + if (((error = git_signature_default(&who, ref->db->repo)) < 0) && + ((error = git_signature_now(&who, "unknown", "unknown")) < 0)) { return error; + } - return 0; + error = reference__rename(out, ref, new_name, force, who, NULL); + + git_signature_free(who); + + return error; +} + +int git_reference_rename_with_log( + git_reference **out, + git_reference *ref, + const char *new_name, + int force, + const git_signature *who, + const char * message) +{ + return reference__rename(out, ref, new_name, force, who, message); } int git_reference_resolve(git_reference **ref_out, const git_reference *ref) @@ -956,22 +1049,30 @@ int git_reference__update_terminal( return reference__update_terminal(repo, ref_name, oid, 0); } -int git_reference_has_log( - git_reference *ref) +int git_reference_has_log(git_repository *repo, const char *refname) { - git_buf path = GIT_BUF_INIT; - int result; + int error; + git_refdb *refdb; - assert(ref); + assert(repo && refname); - if (git_buf_join_n(&path, '/', 3, ref->db->repo->path_repository, - GIT_REFLOG_DIR, ref->name) < 0) - return -1; + if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0) + return error; - result = git_path_isfile(git_buf_cstr(&path)); - git_buf_free(&path); + return git_refdb_has_log(refdb, refname); +} + +int git_reference_ensure_log(git_repository *repo, const char *refname) +{ + int error; + git_refdb *refdb; + + assert(repo && refname); + + if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0) + return error; - return result; + return git_refdb_ensure_log(refdb, refname); } int git_reference__is_branch(const char *ref_name) diff --git a/src/refs.h b/src/refs.h index 80c7703fc..4d5b6dacb 100644 --- a/src/refs.h +++ b/src/refs.h @@ -19,6 +19,7 @@ #define GIT_REFS_HEADS_DIR GIT_REFS_DIR "heads/" #define GIT_REFS_TAGS_DIR GIT_REFS_DIR "tags/" #define GIT_REFS_REMOTES_DIR GIT_REFS_DIR "remotes/" +#define GIT_REFS_NOTES_DIR GIT_REFS_DIR "notes/" #define GIT_REFS_DIR_MODE 0777 #define GIT_REFS_FILE_MODE 0666 diff --git a/src/stash.c b/src/stash.c index eae56966c..3019816ff 100644 --- a/src/stash.c +++ b/src/stash.c @@ -412,25 +412,15 @@ static int update_reflog( const char *message) { git_reference *stash; - git_reflog *reflog = NULL; int error; - if ((error = git_reference_create(&stash, repo, GIT_REFS_STASH_FILE, w_commit_oid, 1)) < 0) - goto cleanup; - - git_reference_free(stash); - - if ((error = git_reflog_read(&reflog, repo, GIT_REFS_STASH_FILE) < 0)) - goto cleanup; + if ((error = git_reference_ensure_log(repo, GIT_REFS_STASH_FILE)) < 0) + return error; - if ((error = git_reflog_append(reflog, w_commit_oid, stasher, message)) < 0) - goto cleanup; + error = git_reference_create_with_log(&stash, repo, GIT_REFS_STASH_FILE, w_commit_oid, 1, stasher, message); - if ((error = git_reflog_write(reflog)) < 0) - goto cleanup; + git_reference_free(stash); -cleanup: - git_reflog_free(reflog); return error; } @@ -638,7 +628,11 @@ int git_stash_drop( entry = git_reflog_entry_byindex(reflog, 0); git_reference_free(stash); - error = git_reference_create(&stash, repo, GIT_REFS_STASH_FILE, &entry->oid_cur, 1); + if ((error = git_reference_create(&stash, repo, GIT_REFS_STASH_FILE, &entry->oid_cur, 1) < 0)) + goto cleanup; + + /* We need to undo the writing that we just did */ + error = git_reflog_write(reflog); } cleanup: |