summaryrefslogtreecommitdiff
path: root/refs.c
diff options
context:
space:
mode:
Diffstat (limited to 'refs.c')
-rw-r--r--refs.c130
1 files changed, 79 insertions, 51 deletions
diff --git a/refs.c b/refs.c
index 1ab0bb54d3..11abdc7f18 100644
--- a/refs.c
+++ b/refs.c
@@ -9,6 +9,7 @@
#include "iterator.h"
#include "refs.h"
#include "refs/refs-internal.h"
+#include "run-command.h"
#include "object-store.h"
#include "object.h"
#include "tag.h"
@@ -16,6 +17,7 @@
#include "worktree.h"
#include "argv-array.h"
#include "repository.h"
+#include "sigchain.h"
/*
* List of all available backends
@@ -321,50 +323,6 @@ int ref_exists(const char *refname)
return refs_ref_exists(get_main_ref_store(the_repository), refname);
}
-static int match_ref_pattern(const char *refname,
- const struct string_list_item *item)
-{
- int matched = 0;
- if (item->util == NULL) {
- if (!wildmatch(item->string, refname, 0))
- matched = 1;
- } else {
- const char *rest;
- if (skip_prefix(refname, item->string, &rest) &&
- (!*rest || *rest == '/'))
- matched = 1;
- }
- return matched;
-}
-
-int ref_filter_match(const char *refname,
- const struct string_list *include_patterns,
- const struct string_list *exclude_patterns)
-{
- struct string_list_item *item;
-
- if (exclude_patterns && exclude_patterns->nr) {
- for_each_string_list_item(item, exclude_patterns) {
- if (match_ref_pattern(refname, item))
- return 0;
- }
- }
-
- if (include_patterns && include_patterns->nr) {
- int found = 0;
- for_each_string_list_item(item, include_patterns) {
- if (match_ref_pattern(refname, item)) {
- found = 1;
- break;
- }
- }
-
- if (!found)
- return 0;
- }
- return 1;
-}
-
static int filter_refs(const char *refname, const struct object_id *oid,
int flags, void *data)
{
@@ -383,7 +341,7 @@ enum peel_status peel_object(const struct object_id *name, struct object_id *oid
if (o->type == OBJ_NONE) {
int type = oid_object_info(the_repository, name, NULL);
- if (type < 0 || !object_as_type(the_repository, o, type, 0))
+ if (type < 0 || !object_as_type(o, type, 0))
return PEEL_INVALID;
}
@@ -1852,14 +1810,14 @@ static struct ref_store *ref_store_init(const char *gitdir,
struct ref_store *get_main_ref_store(struct repository *r)
{
- if (r->refs)
- return r->refs;
+ if (r->refs_private)
+ return r->refs_private;
if (!r->gitdir)
BUG("attempting to get main_ref_store outside of repository");
- r->refs = ref_store_init(r->gitdir, REF_STORE_ALL_CAPS);
- return r->refs;
+ r->refs_private = ref_store_init(r->gitdir, REF_STORE_ALL_CAPS);
+ return r->refs_private;
}
/*
@@ -2030,10 +1988,65 @@ int ref_update_reject_duplicates(struct string_list *refnames,
return 0;
}
+static const char hook_not_found;
+static const char *hook;
+
+static int run_transaction_hook(struct ref_transaction *transaction,
+ const char *state)
+{
+ struct child_process proc = CHILD_PROCESS_INIT;
+ struct strbuf buf = STRBUF_INIT;
+ int ret = 0, i;
+
+ if (hook == &hook_not_found)
+ return ret;
+ if (!hook)
+ hook = find_hook("reference-transaction");
+ if (!hook) {
+ hook = &hook_not_found;
+ return ret;
+ }
+
+ argv_array_pushl(&proc.args, hook, state, NULL);
+ proc.in = -1;
+ proc.stdout_to_stderr = 1;
+ proc.trace2_hook_name = "reference-transaction";
+
+ ret = start_command(&proc);
+ if (ret)
+ return ret;
+
+ sigchain_push(SIGPIPE, SIG_IGN);
+
+ for (i = 0; i < transaction->nr; i++) {
+ struct ref_update *update = transaction->updates[i];
+
+ strbuf_reset(&buf);
+ strbuf_addf(&buf, "%s %s %s\n",
+ oid_to_hex(&update->old_oid),
+ oid_to_hex(&update->new_oid),
+ update->refname);
+
+ if (write_in_full(proc.in, buf.buf, buf.len) < 0) {
+ if (errno != EPIPE)
+ ret = -1;
+ break;
+ }
+ }
+
+ close(proc.in);
+ sigchain_pop(SIGPIPE);
+ strbuf_release(&buf);
+
+ ret |= finish_command(&proc);
+ return ret;
+}
+
int ref_transaction_prepare(struct ref_transaction *transaction,
struct strbuf *err)
{
struct ref_store *refs = transaction->ref_store;
+ int ret;
switch (transaction->state) {
case REF_TRANSACTION_OPEN:
@@ -2056,7 +2069,17 @@ int ref_transaction_prepare(struct ref_transaction *transaction,
return -1;
}
- return refs->be->transaction_prepare(refs, transaction, err);
+ ret = refs->be->transaction_prepare(refs, transaction, err);
+ if (ret)
+ return ret;
+
+ ret = run_transaction_hook(transaction, "prepared");
+ if (ret) {
+ ref_transaction_abort(transaction, err);
+ die(_("ref updates aborted by hook"));
+ }
+
+ return 0;
}
int ref_transaction_abort(struct ref_transaction *transaction,
@@ -2080,6 +2103,8 @@ int ref_transaction_abort(struct ref_transaction *transaction,
break;
}
+ run_transaction_hook(transaction, "aborted");
+
ref_transaction_free(transaction);
return ret;
}
@@ -2108,7 +2133,10 @@ int ref_transaction_commit(struct ref_transaction *transaction,
break;
}
- return refs->be->transaction_finish(refs, transaction, err);
+ ret = refs->be->transaction_finish(refs, transaction, err);
+ if (!ret)
+ run_transaction_hook(transaction, "committed");
+ return ret;
}
int refs_verify_refname_available(struct ref_store *refs,