summaryrefslogtreecommitdiff
path: root/refs/files-backend.c
diff options
context:
space:
mode:
Diffstat (limited to 'refs/files-backend.c')
-rw-r--r--refs/files-backend.c191
1 files changed, 73 insertions, 118 deletions
diff --git a/refs/files-backend.c b/refs/files-backend.c
index e4009b3c42..b288fc97db 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1,16 +1,27 @@
-#include "../cache.h"
-#include "../config.h"
+#include "../git-compat-util.h"
+#include "../copy.h"
+#include "../environment.h"
+#include "../gettext.h"
+#include "../hash.h"
+#include "../hex.h"
#include "../refs.h"
#include "refs-internal.h"
#include "ref-cache.h"
#include "packed-backend.h"
+#include "../ident.h"
#include "../iterator.h"
#include "../dir-iterator.h"
#include "../lockfile.h"
#include "../object.h"
+#include "../object-file.h"
+#include "../path.h"
#include "../dir.h"
#include "../chdir-notify.h"
-#include "worktree.h"
+#include "../setup.h"
+#include "../wrapper.h"
+#include "../write-or-die.h"
+#include "../revision.h"
+#include <wildmatch.h>
/*
* This backend uses the following flags in `ref_update::flags` for
@@ -138,44 +149,30 @@ 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)
{
- switch (ref_type(refname)) {
- case REF_TYPE_PER_WORKTREE:
- case REF_TYPE_PSEUDOREF:
+ const char *bare_refname;
+ const char *wtname;
+ int wtname_len;
+ enum ref_worktree_type wt_type = parse_worktree_ref(
+ refname, &wtname, &wtname_len, &bare_refname);
+
+ switch (wt_type) {
+ case REF_WORKTREE_CURRENT:
strbuf_addf(sb, "%s/logs/%s", refs->base.gitdir, refname);
break;
- case REF_TYPE_OTHER_PSEUDOREF:
- case REF_TYPE_MAIN_PSEUDOREF:
- files_reflog_path_other_worktrees(refs, sb, refname);
+ case REF_WORKTREE_SHARED:
+ case REF_WORKTREE_MAIN:
+ strbuf_addf(sb, "%s/logs/%s", refs->gitcommondir, bare_refname);
break;
- case REF_TYPE_NORMAL:
- strbuf_addf(sb, "%s/logs/%s", refs->gitcommondir, refname);
+ case REF_WORKTREE_OTHER:
+ strbuf_addf(sb, "%s/worktrees/%.*s/logs/%s", refs->gitcommondir,
+ wtname_len, wtname, bare_refname);
break;
default:
- BUG("unknown ref type %d of ref %s",
- ref_type(refname), refname);
+ BUG("unknown ref type %d of ref %s", wt_type, refname);
}
}
@@ -183,22 +180,25 @@ static void files_ref_path(struct files_ref_store *refs,
struct strbuf *sb,
const char *refname)
{
- switch (ref_type(refname)) {
- case REF_TYPE_PER_WORKTREE:
- case REF_TYPE_PSEUDOREF:
+ const char *bare_refname;
+ const char *wtname;
+ int wtname_len;
+ enum ref_worktree_type wt_type = parse_worktree_ref(
+ refname, &wtname, &wtname_len, &bare_refname);
+ switch (wt_type) {
+ case REF_WORKTREE_CURRENT:
strbuf_addf(sb, "%s/%s", refs->base.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);
+ case REF_WORKTREE_OTHER:
+ strbuf_addf(sb, "%s/worktrees/%.*s/%s", refs->gitcommondir,
+ wtname_len, wtname, bare_refname);
+ break;
+ case REF_WORKTREE_SHARED:
+ case REF_WORKTREE_MAIN:
+ strbuf_addf(sb, "%s/%s", refs->gitcommondir, bare_refname);
break;
default:
- BUG("unknown ref type %d of ref %s",
- ref_type(refname), refname);
+ BUG("unknown ref type %d of ref %s", wt_type, refname);
}
}
@@ -244,10 +244,8 @@ static void loose_fill_ref_dir(struct ref_store *ref_store,
int dirnamelen = strlen(dirname);
struct strbuf refname;
struct strbuf path = STRBUF_INIT;
- size_t path_baselen;
files_ref_path(refs, &path, dirname);
- path_baselen = path.len;
d = opendir(path.buf);
if (!d) {
@@ -260,23 +258,22 @@ static void loose_fill_ref_dir(struct ref_store *ref_store,
while ((de = readdir(d)) != NULL) {
struct object_id oid;
- struct stat st;
int flag;
+ unsigned char dtype;
if (de->d_name[0] == '.')
continue;
if (ends_with(de->d_name, ".lock"))
continue;
strbuf_addstr(&refname, de->d_name);
- strbuf_addstr(&path, de->d_name);
- if (stat(path.buf, &st) < 0) {
- ; /* silently ignore */
- } else if (S_ISDIR(st.st_mode)) {
+
+ dtype = get_dtype(de, &path, 1);
+ if (dtype == DT_DIR) {
strbuf_addch(&refname, '/');
add_entry_to_dir(dir,
create_dir_entry(dir->cache, refname.buf,
refname.len));
- } else {
+ } else if (dtype == DT_REG) {
if (!refs_resolve_ref_unsafe(&refs->base,
refname.buf,
RESOLVE_REF_READING,
@@ -306,7 +303,6 @@ static void loose_fill_ref_dir(struct ref_store *ref_store,
create_ref_entry(refname.buf, &oid, flag));
}
strbuf_setlen(&refname, dirnamelen);
- strbuf_setlen(&path, path_baselen);
}
strbuf_release(&refname);
strbuf_release(&path);
@@ -771,7 +767,8 @@ static int files_ref_iterator_advance(struct ref_iterator *ref_iterator)
while ((ok = ref_iterator_advance(iter->iter0)) == ITER_OK) {
if (iter->flags & DO_FOR_EACH_PER_WORKTREE_ONLY &&
- ref_type(iter->iter0->refname) != REF_TYPE_PER_WORKTREE)
+ parse_worktree_ref(iter->iter0->refname, NULL, NULL,
+ NULL) != REF_WORKTREE_CURRENT)
continue;
if ((iter->flags & DO_FOR_EACH_OMIT_DANGLING_SYMREFS) &&
@@ -829,7 +826,8 @@ static struct ref_iterator_vtable files_ref_iterator_vtable = {
static struct ref_iterator *files_ref_iterator_begin(
struct ref_store *ref_store,
- const char *prefix, unsigned int flags)
+ const char *prefix, const char **exclude_patterns,
+ unsigned int flags)
{
struct files_ref_store *refs;
struct ref_iterator *loose_iter, *packed_iter, *overlay_iter;
@@ -874,7 +872,7 @@ static struct ref_iterator *files_ref_iterator_begin(
* the packed and loose references.
*/
packed_iter = refs_ref_iterator_begin(
- refs->packed_ref_store, prefix, 0,
+ refs->packed_ref_store, prefix, exclude_patterns, 0,
DO_FOR_EACH_INCLUDE_BROKEN);
overlay_iter = overlay_ref_iterator_begin(loose_iter, packed_iter);
@@ -1175,14 +1173,13 @@ static void prune_refs(struct files_ref_store *refs, struct ref_to_prune **refs_
*/
static int should_pack_ref(const char *refname,
const struct object_id *oid, unsigned int ref_flags,
- unsigned int pack_flags)
+ struct pack_refs_opts *opts)
{
- /* Do not pack per-worktree refs: */
- if (ref_type(refname) != REF_TYPE_NORMAL)
- return 0;
+ struct string_list_item *item;
- /* Do not pack non-tags unless PACK_REFS_ALL is set: */
- if (!(pack_flags & PACK_REFS_ALL) && !starts_with(refname, "refs/tags/"))
+ /* Do not pack per-worktree refs: */
+ if (parse_worktree_ref(refname, NULL, NULL, NULL) !=
+ REF_WORKTREE_SHARED)
return 0;
/* Do not pack symbolic refs: */
@@ -1193,10 +1190,18 @@ static int should_pack_ref(const char *refname,
if (!ref_resolves_to_object(refname, the_repository, oid, ref_flags))
return 0;
- return 1;
+ if (ref_excluded(opts->exclusions, refname))
+ return 0;
+
+ for_each_string_list_item(item, opts->includes)
+ if (!wildmatch(item->string, refname, 0))
+ return 1;
+
+ return 0;
}
-static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)
+static int files_pack_refs(struct ref_store *ref_store,
+ struct pack_refs_opts *opts)
{
struct files_ref_store *refs =
files_downcast(ref_store, REF_STORE_WRITE | REF_STORE_ODB,
@@ -1221,8 +1226,7 @@ static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)
* in the packed ref cache. If the reference should be
* pruned, also add it to refs_to_prune.
*/
- if (!should_pack_ref(iter->refname, iter->oid, iter->flags,
- flags))
+ if (!should_pack_ref(iter->refname, iter->oid, iter->flags, opts))
continue;
/*
@@ -1236,7 +1240,7 @@ static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)
iter->refname, err.buf);
/* Schedule the loose reference for pruning if requested. */
- if ((flags & PACK_REFS_PRUNE)) {
+ if ((opts->flags & PACK_REFS_PRUNE)) {
struct ref_to_prune *n;
FLEX_ALLOC_STR(n, name, iter->refname);
oidcpy(&n->oid, iter->oid);
@@ -1259,54 +1263,6 @@ static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)
return 0;
}
-static int files_delete_refs(struct ref_store *ref_store, const char *msg,
- struct string_list *refnames, unsigned int flags)
-{
- struct files_ref_store *refs =
- files_downcast(ref_store, REF_STORE_WRITE, "delete_refs");
- struct strbuf err = STRBUF_INIT;
- int i, result = 0;
-
- if (!refnames->nr)
- return 0;
-
- if (packed_refs_lock(refs->packed_ref_store, 0, &err))
- goto error;
-
- if (refs_delete_refs(refs->packed_ref_store, msg, refnames, flags)) {
- packed_refs_unlock(refs->packed_ref_store);
- goto error;
- }
-
- packed_refs_unlock(refs->packed_ref_store);
-
- for (i = 0; i < refnames->nr; i++) {
- const char *refname = refnames->items[i].string;
-
- if (refs_delete_ref(&refs->base, msg, refname, NULL, flags))
- result |= error(_("could not remove reference %s"), refname);
- }
-
- strbuf_release(&err);
- return result;
-
-error:
- /*
- * If we failed to rewrite the packed-refs file, then it is
- * unsafe to try to remove loose refs, because doing so might
- * expose an obsolete packed value for a reference that might
- * even point at an object that has been garbage collected.
- */
- if (refnames->nr == 1)
- error(_("could not delete reference %s: %s"),
- refnames->items[0].string, err.buf);
- else
- error(_("could not delete references: %s"), err.buf);
-
- strbuf_release(&err);
- return -1;
-}
-
/*
* People using contrib's git-new-workdir have .git/logs/refs ->
* /some/other/path/.git/logs/refs, and that may live on another device.
@@ -2267,7 +2223,8 @@ static enum iterator_selection reflog_iterator_select(
*/
return ITER_SELECT_0;
} else if (iter_common) {
- if (ref_type(iter_common->refname) == REF_TYPE_NORMAL)
+ if (parse_worktree_ref(iter_common->refname, NULL, NULL,
+ NULL) == REF_WORKTREE_SHARED)
return ITER_SELECT_1;
/*
@@ -3282,7 +3239,6 @@ static int files_init_db(struct ref_store *ref_store, struct strbuf *err UNUSED)
}
struct ref_storage_be refs_be_files = {
- .next = NULL,
.name = "files",
.init = files_ref_store_create,
.init_db = files_init_db,
@@ -3293,7 +3249,6 @@ struct ref_storage_be refs_be_files = {
.pack_refs = files_pack_refs,
.create_symref = files_create_symref,
- .delete_refs = files_delete_refs,
.rename_ref = files_rename_ref,
.copy_ref = files_copy_ref,