diff options
Diffstat (limited to 'refs')
-rw-r--r-- | refs/files-backend.c | 86 | ||||
-rw-r--r-- | refs/iterator.c | 6 | ||||
-rw-r--r-- | refs/packed-backend.c | 17 | ||||
-rw-r--r-- | refs/packed-backend.h | 2 | ||||
-rw-r--r-- | refs/ref-cache.c | 2 | ||||
-rw-r--r-- | refs/ref-cache.h | 3 | ||||
-rw-r--r-- | refs/refs-internal.h | 20 |
7 files changed, 88 insertions, 48 deletions
diff --git a/refs/files-backend.c b/refs/files-backend.c index a9a066dcfb..dd8abe9185 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -10,6 +10,7 @@ #include "../object.h" #include "../dir.h" #include "../chdir-notify.h" +#include "worktree.h" /* * This backend uses the following flags in `ref_update::flags` for @@ -149,6 +150,25 @@ static struct files_ref_store *files_downcast(struct ref_store *ref_store, return refs; } +static void files_reflog_path_other_worktrees(struct files_ref_store *refs, + struct strbuf *sb, + const char *refname) +{ + const char *real_ref; + const char *worktree_name; + int length; + + if (parse_worktree_ref(refname, &worktree_name, &length, &real_ref)) + BUG("refname %s is not a other-worktree ref", refname); + + if (worktree_name) + strbuf_addf(sb, "%s/worktrees/%.*s/logs/%s", refs->gitcommondir, + length, worktree_name, real_ref); + else + strbuf_addf(sb, "%s/logs/%s", refs->gitcommondir, + real_ref); +} + static void files_reflog_path(struct files_ref_store *refs, struct strbuf *sb, const char *refname) @@ -158,6 +178,10 @@ static void files_reflog_path(struct files_ref_store *refs, case REF_TYPE_PSEUDOREF: strbuf_addf(sb, "%s/logs/%s", refs->gitdir, refname); break; + case REF_TYPE_OTHER_PSEUDOREF: + case REF_TYPE_MAIN_PSEUDOREF: + files_reflog_path_other_worktrees(refs, sb, refname); + break; case REF_TYPE_NORMAL: strbuf_addf(sb, "%s/logs/%s", refs->gitcommondir, refname); break; @@ -176,6 +200,11 @@ static void files_ref_path(struct files_ref_store *refs, case REF_TYPE_PSEUDOREF: strbuf_addf(sb, "%s/%s", refs->gitdir, refname); break; + case REF_TYPE_MAIN_PSEUDOREF: + if (!skip_prefix(refname, "main-worktree/", &refname)) + BUG("ref %s is not a main pseudoref", refname); + /* fallthrough */ + case REF_TYPE_OTHER_PSEUDOREF: case REF_TYPE_NORMAL: strbuf_addf(sb, "%s/%s", refs->gitcommondir, refname); break; @@ -269,9 +298,9 @@ static void loose_fill_ref_dir(struct ref_store *ref_store, closedir(d); /* - * Manually add refs/bisect, which, being per-worktree, might - * not appear in the directory listing for refs/ in the main - * repo. + * Manually add refs/bisect and refs/worktree, which, being + * per-worktree, might not appear in the directory listing for + * refs/ in the main repo. */ if (!strcmp(dirname, "refs/")) { int pos = search_ref_dir(dir, "refs/bisect/", 12); @@ -281,6 +310,14 @@ static void loose_fill_ref_dir(struct ref_store *ref_store, dir->cache, "refs/bisect/", 12, 1); add_entry_to_dir(dir, child_entry); } + + pos = search_ref_dir(dir, "refs/worktree/", 11); + + if (pos < 0) { + struct ref_entry *child_entry = create_dir_entry( + dir->cache, "refs/worktree/", 11, 1); + add_entry_to_dir(dir, child_entry); + } } } @@ -363,7 +400,7 @@ stat_ref: /* Follow "normalized" - ie "refs/.." symlinks by hand */ if (S_ISLNK(st.st_mode)) { strbuf_reset(&sb_contents); - if (strbuf_readlink(&sb_contents, path, 0) < 0) { + if (strbuf_readlink(&sb_contents, path, st.st_size) < 0) { if (errno == ENOENT || errno == EINVAL) /* inconsistent with lstat; retry */ goto stat_ref; @@ -841,7 +878,7 @@ static int verify_lock(struct ref_store *ref_store, struct ref_lock *lock, return 0; } } - if (old_oid && oidcmp(&lock->old_oid, old_oid)) { + if (old_oid && !oideq(&lock->old_oid, old_oid)) { strbuf_addf(err, "ref '%s' is at %s but expected %s", lock->ref_name, oid_to_hex(&lock->old_oid), @@ -1582,26 +1619,17 @@ static int log_ref_write_fd(int fd, const struct object_id *old_oid, const struct object_id *new_oid, const char *committer, const char *msg) { - int msglen, written; - unsigned maxlen, len; - char *logrec; - - msglen = msg ? strlen(msg) : 0; - maxlen = strlen(committer) + msglen + 100; - logrec = xmalloc(maxlen); - len = xsnprintf(logrec, maxlen, "%s %s %s\n", - oid_to_hex(old_oid), - oid_to_hex(new_oid), - committer); - if (msglen) - len += copy_reflog_msg(logrec + len - 1, msg) - 1; - - written = len <= maxlen ? write_in_full(fd, logrec, len) : -1; - free(logrec); - if (written < 0) - return -1; + struct strbuf sb = STRBUF_INIT; + int ret = 0; - return 0; + strbuf_addf(&sb, "%s %s %s", oid_to_hex(old_oid), oid_to_hex(new_oid), committer); + if (msg && *msg) + copy_reflog_msg(&sb, msg); + strbuf_addch(&sb, '\n'); + if (write_in_full(fd, sb.buf, sb.len) < 0) + ret = -1; + strbuf_release(&sb); + return ret; } static int files_log_ref_write(struct files_ref_store *refs, @@ -1660,7 +1688,7 @@ static int write_ref_to_lockfile(struct ref_lock *lock, struct object *o; int fd; - o = parse_object(oid); + o = parse_object(the_repository, oid); if (!o) { strbuf_addf(err, "trying to write ref '%s' with nonexistent object %s", @@ -1676,7 +1704,7 @@ static int write_ref_to_lockfile(struct ref_lock *lock, return -1; } fd = get_lock_file_fd(&lock->lk); - if (write_in_full(fd, oid_to_hex(oid), GIT_SHA1_HEXSZ) < 0 || + if (write_in_full(fd, oid_to_hex(oid), the_hash_algo->hexsz) < 0 || write_in_full(fd, &term, 1) < 0 || close_ref_gently(lock) < 0) { strbuf_addf(err, @@ -2316,7 +2344,7 @@ static int check_old_oid(struct ref_update *update, struct object_id *oid, struct strbuf *err) { if (!(update->flags & REF_HAVE_OLD) || - !oidcmp(oid, &update->old_oid)) + oideq(oid, &update->old_oid)) return 0; if (is_null_oid(&update->old_oid)) @@ -2452,7 +2480,7 @@ static int lock_ref_for_update(struct files_ref_store *refs, !(update->flags & REF_DELETING) && !(update->flags & REF_LOG_ONLY)) { if (!(update->type & REF_ISSYMREF) && - !oidcmp(&lock->old_oid, &update->new_oid)) { + oideq(&lock->old_oid, &update->new_oid)) { /* * The reference already has the desired * value, so we don't need to write it. @@ -3070,7 +3098,7 @@ static int files_reflog_expire(struct ref_store *ref_store, rollback_lock_file(&reflog_lock); } else if (update && (write_in_full(get_lock_file_fd(&lock->lk), - oid_to_hex(&cb.last_kept_oid), GIT_SHA1_HEXSZ) < 0 || + oid_to_hex(&cb.last_kept_oid), the_hash_algo->hexsz) < 0 || write_str_in_full(get_lock_file_fd(&lock->lk), "\n") < 0 || close_ref_gently(lock) < 0)) { status |= error("couldn't write %s", diff --git a/refs/iterator.c b/refs/iterator.c index 2ac91ac340..629e00a122 100644 --- a/refs/iterator.c +++ b/refs/iterator.c @@ -407,15 +407,15 @@ struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0, struct ref_iterator *current_ref_iter = NULL; -int do_for_each_ref_iterator(struct ref_iterator *iter, - each_ref_fn fn, void *cb_data) +int do_for_each_repo_ref_iterator(struct repository *r, struct ref_iterator *iter, + each_repo_ref_fn fn, void *cb_data) { int retval = 0, ok; struct ref_iterator *old_ref_iter = current_ref_iter; current_ref_iter = iter; while ((ok = ref_iterator_advance(iter)) == ITER_OK) { - retval = fn(iter->refname, iter->oid, iter->flags, cb_data); + retval = fn(r, iter->refname, iter->oid, iter->flags, cb_data); if (retval) { /* * If ref_iterator_abort() returns ITER_ERROR, diff --git a/refs/packed-backend.c b/refs/packed-backend.c index cec3fb9e00..c01c7f5901 100644 --- a/refs/packed-backend.c +++ b/refs/packed-backend.c @@ -274,8 +274,8 @@ struct snapshot_record { static int cmp_packed_ref_records(const void *v1, const void *v2) { const struct snapshot_record *e1 = v1, *e2 = v2; - const char *r1 = e1->start + GIT_SHA1_HEXSZ + 1; - const char *r2 = e2->start + GIT_SHA1_HEXSZ + 1; + const char *r1 = e1->start + the_hash_algo->hexsz + 1; + const char *r2 = e2->start + the_hash_algo->hexsz + 1; while (1) { if (*r1 == '\n') @@ -297,7 +297,7 @@ static int cmp_packed_ref_records(const void *v1, const void *v2) */ static int cmp_record_to_refname(const char *rec, const char *refname) { - const char *r1 = rec + GIT_SHA1_HEXSZ + 1; + const char *r1 = rec + the_hash_algo->hexsz + 1; const char *r2 = refname; while (1) { @@ -344,7 +344,7 @@ static void sort_snapshot(struct snapshot *snapshot) if (!eol) /* The safety check should prevent this. */ BUG("unterminated line found in packed-refs"); - if (eol - pos < GIT_SHA1_HEXSZ + 2) + if (eol - pos < the_hash_algo->hexsz + 2) die_invalid_line(snapshot->refs->path, pos, eof - pos); eol++; @@ -456,7 +456,7 @@ static void verify_buffer_safe(struct snapshot *snapshot) return; last_line = find_start_of_record(start, eof - 1); - if (*(eof - 1) != '\n' || eof - last_line < GIT_SHA1_HEXSZ + 2) + if (*(eof - 1) != '\n' || eof - last_line < the_hash_algo->hexsz + 2) die_invalid_line(snapshot->refs->path, last_line, eof - last_line); } @@ -499,6 +499,7 @@ static int load_contents(struct snapshot *snapshot) size = xsize_t(st.st_size); if (!size) { + close(fd); return 0; } else if (mmap_strategy == MMAP_NONE || size <= SMALL_FILE_SIZE) { snapshot->buf = xmalloc(size); @@ -795,7 +796,7 @@ static int next_record(struct packed_ref_iterator *iter) iter->base.flags = REF_ISPACKED; - if (iter->eof - p < GIT_SHA1_HEXSZ + 2 || + if (iter->eof - p < the_hash_algo->hexsz + 2 || parse_oid_hex(p, &iter->oid, &p) || !isspace(*p++)) die_invalid_line(iter->snapshot->refs->path, @@ -825,7 +826,7 @@ static int next_record(struct packed_ref_iterator *iter) if (iter->pos < iter->eof && *iter->pos == '^') { p = iter->pos + 1; - if (iter->eof - p < GIT_SHA1_HEXSZ + 1 || + if (iter->eof - p < the_hash_algo->hexsz + 1 || parse_oid_hex(p, &iter->peeled, &p) || *p++ != '\n') die_invalid_line(iter->snapshot->refs->path, @@ -1159,7 +1160,7 @@ static int write_with_updates(struct packed_ref_store *refs, "reference already exists", update->refname); goto error; - } else if (oidcmp(&update->old_oid, iter->oid)) { + } else if (!oideq(&update->old_oid, iter->oid)) { strbuf_addf(err, "cannot update ref '%s': " "is at %s but expected %s", update->refname, diff --git a/refs/packed-backend.h b/refs/packed-backend.h index 640245d3b9..a01a0aff9c 100644 --- a/refs/packed-backend.h +++ b/refs/packed-backend.h @@ -1,6 +1,8 @@ #ifndef REFS_PACKED_BACKEND_H #define REFS_PACKED_BACKEND_H +struct ref_transaction; + /* * Support for storing references in a `packed-refs` file. * diff --git a/refs/ref-cache.c b/refs/ref-cache.c index 9b110c8494..b7052f72e2 100644 --- a/refs/ref-cache.c +++ b/refs/ref-cache.c @@ -272,7 +272,7 @@ static int is_dup_ref(const struct ref_entry *ref1, const struct ref_entry *ref2 /* This is impossible by construction */ die("Reference directory conflict: %s", ref1->name); - if (oidcmp(&ref1->u.value.oid, &ref2->u.value.oid)) + if (!oideq(&ref1->u.value.oid, &ref2->u.value.oid)) die("Duplicated ref, and SHA1s don't match: %s", ref1->name); warning("Duplicated ref: %s", ref1->name); diff --git a/refs/ref-cache.h b/refs/ref-cache.h index eda65e73ed..3bfb89d2b3 100644 --- a/refs/ref-cache.h +++ b/refs/ref-cache.h @@ -1,7 +1,10 @@ #ifndef REFS_REF_CACHE_H #define REFS_REF_CACHE_H +#include "cache.h" + struct ref_dir; +struct ref_store; /* * If this ref_cache is filled lazily, this function is used to load diff --git a/refs/refs-internal.h b/refs/refs-internal.h index dd834314bd..f2d8c0123a 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -1,6 +1,12 @@ #ifndef REFS_REFS_INTERNAL_H #define REFS_REFS_INTERNAL_H +#include "cache.h" +#include "refs.h" +#include "iterator.h" + +struct ref_transaction; + /* * Data structures and functions for the internal use of the refs * module. Code outside of the refs module should use only the public @@ -91,11 +97,10 @@ enum peel_status { enum peel_status peel_object(const struct object_id *name, struct object_id *oid); /* - * Copy the reflog message msg to buf, which has been allocated sufficiently - * large, while cleaning up the whitespaces. Especially, convert LF to space, - * because reflog file is one line per entry. + * Copy the reflog message msg to sb while cleaning up the whitespaces. + * Especially, convert LF to space, because reflog file is one line per entry. */ -int copy_reflog_msg(char *buf, const char *msg); +void copy_reflog_msg(struct strbuf *sb, const char *msg); /** * Information needed for a single ref update. Set new_oid to the new @@ -281,7 +286,7 @@ int refs_rename_ref_available(struct ref_store *refs, * * // Access information about the current reference: * if (!(iter->flags & REF_ISSYMREF)) - * printf("%s is %s\n", iter->refname, oid_to_hex(&iter->oid)); + * printf("%s is %s\n", iter->refname, oid_to_hex(iter->oid)); * * // If you need to peel the reference: * ref_iterator_peel(iter, &oid); @@ -473,8 +478,9 @@ extern struct ref_iterator *current_ref_iter; * adapter between the callback style of reference iteration and the * iterator style. */ -int do_for_each_ref_iterator(struct ref_iterator *iter, - each_ref_fn fn, void *cb_data); +int do_for_each_repo_ref_iterator(struct repository *r, + struct ref_iterator *iter, + each_repo_ref_fn fn, void *cb_data); /* * Only include per-worktree refs in a do_for_each_ref*() iteration. |