* [PATCH v4 00/26] refs backend pre-vtable patches
@ 2015-10-15 19:46 David Turner
2015-10-15 19:46 ` [PATCH v4 01/26] refs.c: create a public version of verify_refname_available David Turner
` (25 more replies)
0 siblings, 26 replies; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: David Turner
Michael and Junio want to split the refs-backend patches into multiple
sections: pre-vtable, vtable, and maybe lmdb.
This is the pre-vtable section. It includes multiple fixes suggested
by Michael:
1. When we move chunks around between files, make sure we don't cut
new versions and paste old versions!
2. Some rearrangement of patches
3. Made fewer things public, since they are really only needed for
files-backend optimizations.
4. Comment fixes (and moving doc-comments to refs.h when functions
become public)
Also, on my own, I moved Jeff's repository format patch into this
chunk, since it should be relatively non-controversial.
David Turner (9):
refs: make repack_without_refs and is_branch public
refs: move transaction functions into common code
refs.c: move refname_is_safe to the common code
refs.c: move copy_msg to the common code
refs.c: move peel_object to the common code
refs.c: move should_autocreate_reflog to common code
initdb: move safe_create_dir into common code
refs: make files_log_ref_write functions public
refs: break out ref conflict checks
Jeff King (1):
introduce "extensions" form of core.repositoryformatversion
Ronnie Sahlberg (16):
refs.c: create a public version of verify_refname_available
refs-be-files.c: rename refs to refs-be-files
refs.c: add a new refs.c file to hold all common refs code
refs.c: move update_ref to refs.c
refs.c: move delete_pseudoref and delete_ref to the common code
refs.c: move read_ref_at to the common refs file
refs.c: move the hidden refs functions to the common code
refs.c: move dwim and friend functions to the common refs code
refs.c: move warn_if_dangling_symref* to the common code
refs.c: move read_ref, read_ref_full and ref_exists to the common code
refs.c: move resolve_refdup to common
refs.c: move check_refname_format to the common code
refs.c: move is_branch to the common code
refs.c: move prettify_refname to the common code
refs.c: move ref iterators to the common code
refs.c: move head_ref_namespaced to the common code
Documentation/technical/repository-version.txt | 81 +
Makefile | 1 +
builtin/init-db.c | 12 -
cache.h | 11 +
path.c | 12 +
refs-be-files.c | 3513 ++++++++++++++++
refs.c | 5172 ++++--------------------
refs.h | 187 +-
setup.c | 37 +-
t/t1302-repo-version.sh | 38 +
10 files changed, 4645 insertions(+), 4419 deletions(-)
create mode 100644 Documentation/technical/repository-version.txt
create mode 100644 refs-be-files.c
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH v4 01/26] refs.c: create a public version of verify_refname_available
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-15 19:46 ` [PATCH v4 02/26] refs: make repack_without_refs and is_branch public David Turner
` (24 subsequent siblings)
25 siblings, 0 replies; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: Ronnie Sahlberg, David Turner, Junio C Hamano
From: Ronnie Sahlberg <sahlberg@google.com>
Create a public version of verify_refname_available that backends can
provide.
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs.c | 65 ++++++++++++++++++++++++++++++-----------------------------------
refs.h | 20 ++++++++++++++++++++
2 files changed, 50 insertions(+), 35 deletions(-)
diff --git a/refs.c b/refs.c
index 132eff5..fe71ea0 100644
--- a/refs.c
+++ b/refs.c
@@ -279,7 +279,7 @@ struct ref_dir {
* presence of an empty subdirectory does not block the creation of a
* similarly-named reference. (The fact that reference names with the
* same leading components can conflict *with each other* is a
- * separate issue that is regulated by verify_refname_available().)
+ * separate issue that is regulated by verify_refname_available_dir().)
*
* Please note that the name field contains the fully-qualified
* reference (or subdirectory) name. Space could be saved by only
@@ -897,25 +897,13 @@ static int nonmatching_ref_fn(struct ref_entry *entry, void *vdata)
/*
* Return 0 if a reference named refname could be created without
* conflicting with the name of an existing reference in dir.
- * Otherwise, return a negative value and write an explanation to err.
- * If extras is non-NULL, it is a list of additional refnames with
- * which refname is not allowed to conflict. If skip is non-NULL,
- * ignore potential conflicts with refs in skip (e.g., because they
- * are scheduled for deletion in the same operation). Behavior is
- * undefined if the same name is listed in both extras and skip.
- *
- * Two reference names conflict if one of them exactly matches the
- * leading components of the other; e.g., "refs/foo/bar" conflicts
- * with both "refs/foo" and with "refs/foo/bar/baz" but not with
- * "refs/foo/bar" or "refs/foo/barbados".
- *
- * extras and skip must be sorted.
+ * See verify_refname_available for details.
*/
-static int verify_refname_available(const char *refname,
- const struct string_list *extras,
- const struct string_list *skip,
- struct ref_dir *dir,
- struct strbuf *err)
+static int verify_refname_available_dir(const char *refname,
+ const struct string_list *extras,
+ const struct string_list *skip,
+ struct ref_dir *dir,
+ struct strbuf *err)
{
const char *slash;
int pos;
@@ -2464,9 +2452,12 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
*/
strbuf_git_path(&orig_ref_file, "%s", orig_refname);
if (remove_empty_directories(&orig_ref_file)) {
+ struct ref_dir *loose_refs;
+ loose_refs = get_loose_refs(&ref_cache);
last_errno = errno;
- if (!verify_refname_available(orig_refname, extras, skip,
- get_loose_refs(&ref_cache), err))
+ if (!verify_refname_available_dir(orig_refname, extras,
+ skip, loose_refs,
+ err))
strbuf_addf(err, "there are still refs under '%s'",
orig_refname);
goto error_return;
@@ -2479,8 +2470,9 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
if (!refname) {
last_errno = errno;
if (last_errno != ENOTDIR ||
- !verify_refname_available(orig_refname, extras, skip,
- get_loose_refs(&ref_cache), err))
+ !verify_refname_available_dir(orig_refname, extras, skip,
+ get_loose_refs(&ref_cache),
+ err))
strbuf_addf(err, "unable to resolve reference %s: %s",
orig_refname, strerror(last_errno));
@@ -2493,8 +2485,8 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
* our refname.
*/
if (is_null_oid(&lock->old_oid) &&
- verify_refname_available(refname, extras, skip,
- get_packed_refs(&ref_cache), err)) {
+ verify_refname_available_dir(refname, extras, skip,
+ get_packed_refs(&ref_cache), err)) {
last_errno = ENOTDIR;
goto error_return;
}
@@ -3127,10 +3119,7 @@ static int rename_ref_available(const char *oldname, const char *newname)
int ret;
string_list_insert(&skip, oldname);
- ret = !verify_refname_available(newname, NULL, &skip,
- get_packed_refs(&ref_cache), &err)
- && !verify_refname_available(newname, NULL, &skip,
- get_loose_refs(&ref_cache), &err);
+ ret = !verify_refname_available(newname, NULL, &skip, &err);
if (!ret)
error("%s", err.buf);
@@ -3299,6 +3288,17 @@ static int should_autocreate_reflog(const char *refname)
!strcmp(refname, "HEAD");
}
+int verify_refname_available(const char *newname, struct string_list *extra,
+ struct string_list *skip, struct strbuf *err)
+{
+ struct ref_dir *packed_refs = get_packed_refs(&ref_cache);
+ struct ref_dir *loose_refs = get_loose_refs(&ref_cache);
+ return verify_refname_available_dir(newname, extra, skip,
+ packed_refs, err) ||
+ verify_refname_available_dir(newname, extra, skip,
+ loose_refs, err);
+}
+
/*
* Create a reflog for a ref. If force_create = 0, the reflog will
* only be created for certain refs (those for which
@@ -4334,8 +4334,6 @@ static int ref_present(const char *refname,
int initial_ref_transaction_commit(struct ref_transaction *transaction,
struct strbuf *err)
{
- struct ref_dir *loose_refs = get_loose_refs(&ref_cache);
- struct ref_dir *packed_refs = get_packed_refs(&ref_cache);
int ret = 0, i;
int n = transaction->nr;
struct ref_update **updates = transaction->updates;
@@ -4378,10 +4376,7 @@ int initial_ref_transaction_commit(struct ref_transaction *transaction,
die("BUG: initial ref transaction with old_sha1 set");
if (verify_refname_available(update->refname,
&affected_refnames, NULL,
- loose_refs, err) ||
- verify_refname_available(update->refname,
- &affected_refnames, NULL,
- packed_refs, err)) {
+ err)) {
ret = TRANSACTION_NAME_CONFLICT;
goto cleanup;
}
diff --git a/refs.h b/refs.h
index 6d30c98..7367a7f 100644
--- a/refs.h
+++ b/refs.h
@@ -218,6 +218,26 @@ extern void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, const struct st
int pack_refs(unsigned int flags);
/*
+ * Return 0 if a reference named refname could be created without
+ * conflicting with the name of an existing reference.
+ * Otherwise, return a negative value and write an explanation to err.
+ * If extras is non-NULL, it is a list of additional refnames with
+ * which refname is not allowed to conflict. If skip is non-NULL,
+ * ignore potential conflicts with refs in skip (e.g., because they
+ * are scheduled for deletion in the same operation). Behavior is
+ * undefined if the same name is listed in both extras and skip.
+ *
+ * Two reference names conflict if one of them exactly matches the
+ * leading components of the other; e.g., "foo/bar" conflicts with
+ * both "foo" and with "foo/bar/baz" but not with "foo/bar" or
+ * "foo/barbados".
+ *
+ * skip must be sorted.
+ */
+int verify_refname_available(const char *newname, struct string_list *extra,
+ struct string_list *skip, struct strbuf *err);
+
+/*
* Flags controlling ref_transaction_update(), ref_transaction_create(), etc.
* REF_NODEREF: act on the ref directly, instead of dereferencing
* symbolic references.
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v4 02/26] refs: make repack_without_refs and is_branch public
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
2015-10-15 19:46 ` [PATCH v4 01/26] refs.c: create a public version of verify_refname_available David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-16 6:34 ` Michael Haggerty
2015-10-15 19:46 ` [PATCH v4 03/26] refs-be-files.c: rename refs to refs-be-files David Turner
` (23 subsequent siblings)
25 siblings, 1 reply; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: David Turner, Ronnie Sahlberg, Junio C Hamano
is_branch was already non-static, but this patch declares it in the
header.
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs.c | 5 +++--
refs.h | 2 ++
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/refs.c b/refs.c
index fe71ea0..84abc82 100644
--- a/refs.c
+++ b/refs.c
@@ -2816,8 +2816,9 @@ int pack_refs(unsigned int flags)
/*
* Rewrite the packed-refs file, omitting any refs listed in
- * 'refnames'. On error, leave packed-refs unchanged, write an error
- * message to 'err', and return a nonzero value.
+ * 'refnames'. On error, packed-refs will be unchanged, the return
+ * value is nonzero, and a message about the error is written to the
+ * 'err' strbuf.
*
* The refs in 'refnames' needn't be sorted. `err` must not be NULL.
*/
diff --git a/refs.h b/refs.h
index 7367a7f..8408bef 100644
--- a/refs.h
+++ b/refs.h
@@ -237,6 +237,8 @@ int pack_refs(unsigned int flags);
int verify_refname_available(const char *newname, struct string_list *extra,
struct string_list *skip, struct strbuf *err);
+extern int is_branch(const char *refname);
+
/*
* Flags controlling ref_transaction_update(), ref_transaction_create(), etc.
* REF_NODEREF: act on the ref directly, instead of dereferencing
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v4 03/26] refs-be-files.c: rename refs to refs-be-files
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
2015-10-15 19:46 ` [PATCH v4 01/26] refs.c: create a public version of verify_refname_available David Turner
2015-10-15 19:46 ` [PATCH v4 02/26] refs: make repack_without_refs and is_branch public David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-16 6:36 ` Michael Haggerty
2015-10-15 19:46 ` [PATCH v4 04/26] refs.c: add a new refs.c file to hold all common refs code David Turner
` (22 subsequent siblings)
25 siblings, 1 reply; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: Ronnie Sahlberg, Junio C Hamano
From: Ronnie Sahlberg <sahlberg@google.com>
Rename refs.c to refs-be-files.c to indicate that this file now
holds the implementation for the files based refs backend.
A smaller portion of the code in this file is backend agnostic and will
be moved to a a new refs.c file that will hold all the common refs code
that is shared across all backends.
A second reason for first moving all the code to the new file and then
move the backend agnostic code back to refs.c instead of the other way
around is because the code that will eventually remain in this new
refs-be-files.c file is so entangled that it would then be very
difficult to break the split up into small independent patches/chunks.
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
Makefile | 2 +-
refs.c => refs-be-files.c | 0
2 files changed, 1 insertion(+), 1 deletion(-)
rename refs.c => refs-be-files.c (100%)
diff --git a/Makefile b/Makefile
index 0d9f5dd..173b9d4 100644
--- a/Makefile
+++ b/Makefile
@@ -762,7 +762,7 @@ LIB_OBJS += quote.o
LIB_OBJS += reachable.o
LIB_OBJS += read-cache.o
LIB_OBJS += reflog-walk.o
-LIB_OBJS += refs.o
+LIB_OBJS += refs-be-files.o
LIB_OBJS += ref-filter.o
LIB_OBJS += remote.o
LIB_OBJS += replace_object.o
diff --git a/refs.c b/refs-be-files.c
similarity index 100%
rename from refs.c
rename to refs-be-files.c
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v4 04/26] refs.c: add a new refs.c file to hold all common refs code
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
` (2 preceding siblings ...)
2015-10-15 19:46 ` [PATCH v4 03/26] refs-be-files.c: rename refs to refs-be-files David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-15 19:46 ` [PATCH v4 05/26] refs.c: move update_ref to refs.c David Turner
` (21 subsequent siblings)
25 siblings, 0 replies; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: Ronnie Sahlberg, Junio C Hamano
From: Ronnie Sahlberg <sahlberg@google.com>
Create a new refs.c file that will be used to hold all the refs
code that is backend agnostic and will be shared across all backends.
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
Makefile | 1 +
refs.c | 3 +++
2 files changed, 4 insertions(+)
create mode 100644 refs.c
diff --git a/Makefile b/Makefile
index 173b9d4..b37eae3 100644
--- a/Makefile
+++ b/Makefile
@@ -763,6 +763,7 @@ LIB_OBJS += reachable.o
LIB_OBJS += read-cache.o
LIB_OBJS += reflog-walk.o
LIB_OBJS += refs-be-files.o
+LIB_OBJS += refs.o
LIB_OBJS += ref-filter.o
LIB_OBJS += remote.o
LIB_OBJS += replace_object.o
diff --git a/refs.c b/refs.c
new file mode 100644
index 0000000..77492ff
--- /dev/null
+++ b/refs.c
@@ -0,0 +1,3 @@
+/*
+ * Common refs code for all backends.
+ */
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v4 05/26] refs.c: move update_ref to refs.c
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
` (3 preceding siblings ...)
2015-10-15 19:46 ` [PATCH v4 04/26] refs.c: add a new refs.c file to hold all common refs code David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-21 19:03 ` David Turner
2015-10-15 19:46 ` [PATCH v4 06/26] refs.c: move delete_pseudoref and delete_ref to the common code David Turner
` (20 subsequent siblings)
25 siblings, 1 reply; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: Ronnie Sahlberg, David Turner, Junio C Hamano
From: Ronnie Sahlberg <sahlberg@google.com>
Move update_ref() to the refs.c file since this function does not
contain any backend specific code. Move the ref classifier functions
as well, since update_ref depends on them.
Based on Ronnie Sahlberg's patch
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs-be-files.c | 117 +-------------------------------------------------------
refs.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 117 insertions(+), 116 deletions(-)
diff --git a/refs-be-files.c b/refs-be-files.c
index 84abc82..72a9bc4 100644
--- a/refs-be-files.c
+++ b/refs-be-files.c
@@ -2675,8 +2675,6 @@ struct pack_refs_cb_data {
struct ref_to_prune *ref_to_prune;
};
-static int is_per_worktree_ref(const char *refname);
-
/*
* An each_ref_entry_fn that is run over loose references only. If
* the loose reference can be packed, add an entry in the packed ref
@@ -2691,7 +2689,7 @@ static int pack_if_possible_fn(struct ref_entry *entry, void *cb_data)
int is_tag_ref = starts_with(entry->name, "refs/tags/");
/* Do not pack per-worktree refs: */
- if (is_per_worktree_ref(entry->name))
+ if (ref_type(entry->name) == REF_TYPE_PER_WORKTREE)
return 0;
/* ALWAYS pack tags */
@@ -2887,77 +2885,6 @@ static int delete_ref_loose(struct ref_lock *lock, int flag, struct strbuf *err)
return 0;
}
-static int is_per_worktree_ref(const char *refname)
-{
- return !strcmp(refname, "HEAD") ||
- starts_with(refname, "refs/bisect/");
-}
-
-static int is_pseudoref_syntax(const char *refname)
-{
- const char *c;
-
- for (c = refname; *c; c++) {
- if (!isupper(*c) && *c != '-' && *c != '_')
- return 0;
- }
-
- return 1;
-}
-
-enum ref_type ref_type(const char *refname)
-{
- if (is_per_worktree_ref(refname))
- return REF_TYPE_PER_WORKTREE;
- if (is_pseudoref_syntax(refname))
- return REF_TYPE_PSEUDOREF;
- return REF_TYPE_NORMAL;
-}
-
-static int write_pseudoref(const char *pseudoref, const unsigned char *sha1,
- const unsigned char *old_sha1, struct strbuf *err)
-{
- const char *filename;
- int fd;
- static struct lock_file lock;
- struct strbuf buf = STRBUF_INIT;
- int ret = -1;
-
- strbuf_addf(&buf, "%s\n", sha1_to_hex(sha1));
-
- filename = git_path("%s", pseudoref);
- fd = hold_lock_file_for_update(&lock, filename, LOCK_DIE_ON_ERROR);
- if (fd < 0) {
- strbuf_addf(err, "Could not open '%s' for writing: %s",
- filename, strerror(errno));
- return -1;
- }
-
- if (old_sha1) {
- unsigned char actual_old_sha1[20];
-
- if (read_ref(pseudoref, actual_old_sha1))
- die("could not read ref '%s'", pseudoref);
- if (hashcmp(actual_old_sha1, old_sha1)) {
- strbuf_addf(err, "Unexpected sha1 when writing %s", pseudoref);
- rollback_lock_file(&lock);
- goto done;
- }
- }
-
- if (write_in_full(fd, buf.buf, buf.len) != buf.len) {
- strbuf_addf(err, "Could not write to '%s'", filename);
- rollback_lock_file(&lock);
- goto done;
- }
-
- commit_lock_file(&lock);
- ret = 0;
-done:
- strbuf_release(&buf);
- return ret;
-}
-
static int delete_pseudoref(const char *pseudoref, const unsigned char *old_sha1)
{
static struct lock_file lock;
@@ -4106,48 +4033,6 @@ int ref_transaction_verify(struct ref_transaction *transaction,
flags, NULL, err);
}
-int update_ref(const char *msg, const char *refname,
- const unsigned char *new_sha1, const unsigned char *old_sha1,
- unsigned int flags, enum action_on_err onerr)
-{
- struct ref_transaction *t = NULL;
- struct strbuf err = STRBUF_INIT;
- int ret = 0;
-
- if (ref_type(refname) == REF_TYPE_PSEUDOREF) {
- ret = write_pseudoref(refname, new_sha1, old_sha1, &err);
- } else {
- t = ref_transaction_begin(&err);
- if (!t ||
- ref_transaction_update(t, refname, new_sha1, old_sha1,
- flags, msg, &err) ||
- ref_transaction_commit(t, &err)) {
- ret = 1;
- ref_transaction_free(t);
- }
- }
- if (ret) {
- const char *str = "update_ref failed for ref '%s': %s";
-
- switch (onerr) {
- case UPDATE_REFS_MSG_ON_ERR:
- error(str, refname, err.buf);
- break;
- case UPDATE_REFS_DIE_ON_ERR:
- die(str, refname, err.buf);
- break;
- case UPDATE_REFS_QUIET_ON_ERR:
- break;
- }
- strbuf_release(&err);
- return 1;
- }
- strbuf_release(&err);
- if (t)
- ref_transaction_free(t);
- return 0;
-}
-
static int ref_update_reject_duplicates(struct string_list *refnames,
struct strbuf *err)
{
diff --git a/refs.c b/refs.c
index 77492ff..610fab0 100644
--- a/refs.c
+++ b/refs.c
@@ -1,3 +1,119 @@
/*
* Common refs code for all backends.
*/
+#include "cache.h"
+#include "refs.h"
+#include "lockfile.h"
+
+static int is_per_worktree_ref(const char *refname)
+{
+ return !strcmp(refname, "HEAD") ||
+ starts_with(refname, "refs/bisect/");
+}
+
+static int is_pseudoref_syntax(const char *refname)
+{
+ const char *c;
+
+ for (c = refname; *c; c++) {
+ if (!isupper(*c) && *c != '-' && *c != '_')
+ return 0;
+ }
+
+ return 1;
+}
+
+enum ref_type ref_type(const char *refname)
+{
+ if (is_per_worktree_ref(refname))
+ return REF_TYPE_PER_WORKTREE;
+ if (is_pseudoref_syntax(refname))
+ return REF_TYPE_PSEUDOREF;
+ return REF_TYPE_NORMAL;
+}
+
+static int write_pseudoref(const char *pseudoref, const unsigned char *sha1,
+ const unsigned char *old_sha1, struct strbuf *err)
+{
+ const char *filename;
+ int fd;
+ static struct lock_file lock;
+ struct strbuf buf = STRBUF_INIT;
+ int ret = -1;
+
+ strbuf_addf(&buf, "%s\n", sha1_to_hex(sha1));
+
+ filename = git_path("%s", pseudoref);
+ fd = hold_lock_file_for_update(&lock, filename, LOCK_DIE_ON_ERROR);
+ if (fd < 0) {
+ strbuf_addf(err, "Could not open '%s' for writing: %s",
+ filename, strerror(errno));
+ return -1;
+ }
+
+ if (old_sha1) {
+ unsigned char actual_old_sha1[20];
+
+ if (read_ref(pseudoref, actual_old_sha1))
+ die("could not read ref '%s'", pseudoref);
+ if (hashcmp(actual_old_sha1, old_sha1)) {
+ strbuf_addf(err, "Unexpected sha1 when writing %s", pseudoref);
+ rollback_lock_file(&lock);
+ goto done;
+ }
+ }
+
+ if (write_in_full(fd, buf.buf, buf.len) != buf.len) {
+ strbuf_addf(err, "Could not write to '%s'", filename);
+ rollback_lock_file(&lock);
+ goto done;
+ }
+
+ commit_lock_file(&lock);
+ ret = 0;
+done:
+ strbuf_release(&buf);
+ return ret;
+}
+
+int update_ref(const char *msg, const char *refname,
+ const unsigned char *new_sha1, const unsigned char *old_sha1,
+ unsigned int flags, enum action_on_err onerr)
+{
+ struct ref_transaction *t = NULL;
+ struct strbuf err = STRBUF_INIT;
+ int ret = 0;
+
+ if (ref_type(refname) == REF_TYPE_PSEUDOREF) {
+ ret = write_pseudoref(refname, new_sha1, old_sha1, &err);
+ } else {
+ t = ref_transaction_begin(&err);
+ if (!t ||
+ ref_transaction_update(t, refname, new_sha1, old_sha1,
+ flags, msg, &err) ||
+ ref_transaction_commit(t, &err)) {
+ ret = 1;
+ ref_transaction_free(t);
+ }
+ }
+ if (ret) {
+ const char *str = "update_ref failed for ref '%s': %s";
+
+ switch (onerr) {
+ case UPDATE_REFS_MSG_ON_ERR:
+ error(str, refname, err.buf);
+ break;
+ case UPDATE_REFS_DIE_ON_ERR:
+ die(str, refname, err.buf);
+ break;
+ case UPDATE_REFS_QUIET_ON_ERR:
+ break;
+ }
+ strbuf_release(&err);
+ return 1;
+ }
+ strbuf_release(&err);
+ if (t)
+ ref_transaction_free(t);
+ return 0;
+}
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v4 06/26] refs.c: move delete_pseudoref and delete_ref to the common code
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
` (4 preceding siblings ...)
2015-10-15 19:46 ` [PATCH v4 05/26] refs.c: move update_ref to refs.c David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-21 19:04 ` David Turner
2015-10-15 19:46 ` [PATCH v4 07/26] refs.c: move read_ref_at to the common refs file David Turner
` (19 subsequent siblings)
25 siblings, 1 reply; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: Ronnie Sahlberg, David Turner, Junio C Hamano
From: Ronnie Sahlberg <sahlberg@google.com>
Move delete_pseudoref() and delete_ref() to the refs.c file since
these functions do not contain any backend specific code. We can't
move delete_refs yet because it depends on the files-backend-specific
repack_without_refs.
Based on a patch by Ronnie Sahlberg.
Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs-be-files.c | 56 --------------------------------------------------------
refs.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 57 insertions(+), 56 deletions(-)
diff --git a/refs-be-files.c b/refs-be-files.c
index 72a9bc4..d969066 100644
--- a/refs-be-files.c
+++ b/refs-be-files.c
@@ -2885,62 +2885,6 @@ static int delete_ref_loose(struct ref_lock *lock, int flag, struct strbuf *err)
return 0;
}
-static int delete_pseudoref(const char *pseudoref, const unsigned char *old_sha1)
-{
- static struct lock_file lock;
- const char *filename;
-
- filename = git_path("%s", pseudoref);
-
- if (old_sha1 && !is_null_sha1(old_sha1)) {
- int fd;
- unsigned char actual_old_sha1[20];
-
- fd = hold_lock_file_for_update(&lock, filename,
- LOCK_DIE_ON_ERROR);
- if (fd < 0)
- die_errno(_("Could not open '%s' for writing"), filename);
- if (read_ref(pseudoref, actual_old_sha1))
- die("could not read ref '%s'", pseudoref);
- if (hashcmp(actual_old_sha1, old_sha1)) {
- warning("Unexpected sha1 when deleting %s", pseudoref);
- rollback_lock_file(&lock);
- return -1;
- }
-
- unlink(filename);
- rollback_lock_file(&lock);
- } else {
- unlink(filename);
- }
-
- return 0;
-}
-
-int delete_ref(const char *refname, const unsigned char *old_sha1,
- unsigned int flags)
-{
- struct ref_transaction *transaction;
- struct strbuf err = STRBUF_INIT;
-
- if (ref_type(refname) == REF_TYPE_PSEUDOREF)
- return delete_pseudoref(refname, old_sha1);
-
- transaction = ref_transaction_begin(&err);
- if (!transaction ||
- ref_transaction_delete(transaction, refname, old_sha1,
- flags, NULL, &err) ||
- ref_transaction_commit(transaction, &err)) {
- error("%s", err.buf);
- ref_transaction_free(transaction);
- strbuf_release(&err);
- return 1;
- }
- ref_transaction_free(transaction);
- strbuf_release(&err);
- return 0;
-}
-
int delete_refs(struct string_list *refnames)
{
struct strbuf err = STRBUF_INIT;
diff --git a/refs.c b/refs.c
index 610fab0..f4f0677 100644
--- a/refs.c
+++ b/refs.c
@@ -117,3 +117,60 @@ int update_ref(const char *msg, const char *refname,
ref_transaction_free(t);
return 0;
}
+
+
+static int delete_pseudoref(const char *pseudoref, const unsigned char *old_sha1)
+{
+ static struct lock_file lock;
+ const char *filename;
+
+ filename = git_path("%s", pseudoref);
+
+ if (old_sha1 && !is_null_sha1(old_sha1)) {
+ int fd;
+ unsigned char actual_old_sha1[20];
+
+ fd = hold_lock_file_for_update(&lock, filename,
+ LOCK_DIE_ON_ERROR);
+ if (fd < 0)
+ die_errno(_("Could not open '%s' for writing"), filename);
+ if (read_ref(pseudoref, actual_old_sha1))
+ die("could not read ref '%s'", pseudoref);
+ if (hashcmp(actual_old_sha1, old_sha1)) {
+ warning("Unexpected sha1 when deleting %s", pseudoref);
+ rollback_lock_file(&lock);
+ return -1;
+ }
+
+ unlink(filename);
+ rollback_lock_file(&lock);
+ } else {
+ unlink(filename);
+ }
+
+ return 0;
+}
+
+int delete_ref(const char *refname, const unsigned char *old_sha1,
+ unsigned int flags)
+{
+ struct ref_transaction *transaction;
+ struct strbuf err = STRBUF_INIT;
+
+ if (ref_type(refname) == REF_TYPE_PSEUDOREF)
+ return delete_pseudoref(refname, old_sha1);
+
+ transaction = ref_transaction_begin(&err);
+ if (!transaction ||
+ ref_transaction_delete(transaction, refname, old_sha1,
+ flags, NULL, &err) ||
+ ref_transaction_commit(transaction, &err)) {
+ error("%s", err.buf);
+ ref_transaction_free(transaction);
+ strbuf_release(&err);
+ return 1;
+ }
+ ref_transaction_free(transaction);
+ strbuf_release(&err);
+ return 0;
+}
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v4 07/26] refs.c: move read_ref_at to the common refs file
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
` (5 preceding siblings ...)
2015-10-15 19:46 ` [PATCH v4 06/26] refs.c: move delete_pseudoref and delete_ref to the common code David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-15 19:46 ` [PATCH v4 08/26] refs.c: move the hidden refs functions to the common code David Turner
` (18 subsequent siblings)
25 siblings, 0 replies; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: Ronnie Sahlberg, David Turner, Junio C Hamano
From: Ronnie Sahlberg <sahlberg@google.com>
Move read_ref_at() to the refs.c file since this function does not
contain any backend specific code.
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs-be-files.c | 118 --------------------------------------------------------
refs.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 118 insertions(+), 118 deletions(-)
diff --git a/refs-be-files.c b/refs-be-files.c
index d969066..04c3206 100644
--- a/refs-be-files.c
+++ b/refs-be-files.c
@@ -3470,124 +3470,6 @@ int create_symref(const char *ref_target, const char *refs_heads_master,
return 0;
}
-struct read_ref_at_cb {
- const char *refname;
- unsigned long at_time;
- int cnt;
- int reccnt;
- unsigned char *sha1;
- int found_it;
-
- unsigned char osha1[20];
- unsigned char nsha1[20];
- int tz;
- unsigned long date;
- char **msg;
- unsigned long *cutoff_time;
- int *cutoff_tz;
- int *cutoff_cnt;
-};
-
-static int read_ref_at_ent(unsigned char *osha1, unsigned char *nsha1,
- const char *email, unsigned long timestamp, int tz,
- const char *message, void *cb_data)
-{
- struct read_ref_at_cb *cb = cb_data;
-
- cb->reccnt++;
- cb->tz = tz;
- cb->date = timestamp;
-
- if (timestamp <= cb->at_time || cb->cnt == 0) {
- if (cb->msg)
- *cb->msg = xstrdup(message);
- if (cb->cutoff_time)
- *cb->cutoff_time = timestamp;
- if (cb->cutoff_tz)
- *cb->cutoff_tz = tz;
- if (cb->cutoff_cnt)
- *cb->cutoff_cnt = cb->reccnt - 1;
- /*
- * we have not yet updated cb->[n|o]sha1 so they still
- * hold the values for the previous record.
- */
- if (!is_null_sha1(cb->osha1)) {
- hashcpy(cb->sha1, nsha1);
- if (hashcmp(cb->osha1, nsha1))
- warning("Log for ref %s has gap after %s.",
- cb->refname, show_date(cb->date, cb->tz, DATE_MODE(RFC2822)));
- }
- else if (cb->date == cb->at_time)
- hashcpy(cb->sha1, nsha1);
- else if (hashcmp(nsha1, cb->sha1))
- warning("Log for ref %s unexpectedly ended on %s.",
- cb->refname, show_date(cb->date, cb->tz,
- DATE_MODE(RFC2822)));
- hashcpy(cb->osha1, osha1);
- hashcpy(cb->nsha1, nsha1);
- cb->found_it = 1;
- return 1;
- }
- hashcpy(cb->osha1, osha1);
- hashcpy(cb->nsha1, nsha1);
- if (cb->cnt > 0)
- cb->cnt--;
- return 0;
-}
-
-static int read_ref_at_ent_oldest(unsigned char *osha1, unsigned char *nsha1,
- const char *email, unsigned long timestamp,
- int tz, const char *message, void *cb_data)
-{
- struct read_ref_at_cb *cb = cb_data;
-
- if (cb->msg)
- *cb->msg = xstrdup(message);
- if (cb->cutoff_time)
- *cb->cutoff_time = timestamp;
- if (cb->cutoff_tz)
- *cb->cutoff_tz = tz;
- if (cb->cutoff_cnt)
- *cb->cutoff_cnt = cb->reccnt;
- hashcpy(cb->sha1, osha1);
- if (is_null_sha1(cb->sha1))
- hashcpy(cb->sha1, nsha1);
- /* We just want the first entry */
- return 1;
-}
-
-int read_ref_at(const char *refname, unsigned int flags, unsigned long at_time, int cnt,
- unsigned char *sha1, char **msg,
- unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt)
-{
- struct read_ref_at_cb cb;
-
- memset(&cb, 0, sizeof(cb));
- cb.refname = refname;
- cb.at_time = at_time;
- cb.cnt = cnt;
- cb.msg = msg;
- cb.cutoff_time = cutoff_time;
- cb.cutoff_tz = cutoff_tz;
- cb.cutoff_cnt = cutoff_cnt;
- cb.sha1 = sha1;
-
- for_each_reflog_ent_reverse(refname, read_ref_at_ent, &cb);
-
- if (!cb.reccnt) {
- if (flags & GET_SHA1_QUIETLY)
- exit(128);
- else
- die("Log for %s is empty.", refname);
- }
- if (cb.found_it)
- return 0;
-
- for_each_reflog_ent(refname, read_ref_at_ent_oldest, &cb);
-
- return 1;
-}
-
int reflog_exists(const char *refname)
{
struct stat st;
diff --git a/refs.c b/refs.c
index f4f0677..8245118 100644
--- a/refs.c
+++ b/refs.c
@@ -174,3 +174,121 @@ int delete_ref(const char *refname, const unsigned char *old_sha1,
strbuf_release(&err);
return 0;
}
+
+struct read_ref_at_cb {
+ const char *refname;
+ unsigned long at_time;
+ int cnt;
+ int reccnt;
+ unsigned char *sha1;
+ int found_it;
+
+ unsigned char osha1[20];
+ unsigned char nsha1[20];
+ int tz;
+ unsigned long date;
+ char **msg;
+ unsigned long *cutoff_time;
+ int *cutoff_tz;
+ int *cutoff_cnt;
+};
+
+static int read_ref_at_ent(unsigned char *osha1, unsigned char *nsha1,
+ const char *email, unsigned long timestamp, int tz,
+ const char *message, void *cb_data)
+{
+ struct read_ref_at_cb *cb = cb_data;
+
+ cb->reccnt++;
+ cb->tz = tz;
+ cb->date = timestamp;
+
+ if (timestamp <= cb->at_time || cb->cnt == 0) {
+ if (cb->msg)
+ *cb->msg = xstrdup(message);
+ if (cb->cutoff_time)
+ *cb->cutoff_time = timestamp;
+ if (cb->cutoff_tz)
+ *cb->cutoff_tz = tz;
+ if (cb->cutoff_cnt)
+ *cb->cutoff_cnt = cb->reccnt - 1;
+ /*
+ * we have not yet updated cb->[n|o]sha1 so they still
+ * hold the values for the previous record.
+ */
+ if (!is_null_sha1(cb->osha1)) {
+ hashcpy(cb->sha1, nsha1);
+ if (hashcmp(cb->osha1, nsha1))
+ warning("Log for ref %s has gap after %s.",
+ cb->refname, show_date(cb->date, cb->tz, DATE_MODE(RFC2822)));
+ }
+ else if (cb->date == cb->at_time)
+ hashcpy(cb->sha1, nsha1);
+ else if (hashcmp(nsha1, cb->sha1))
+ warning("Log for ref %s unexpectedly ended on %s.",
+ cb->refname, show_date(cb->date, cb->tz,
+ DATE_MODE(RFC2822)));
+ hashcpy(cb->osha1, osha1);
+ hashcpy(cb->nsha1, nsha1);
+ cb->found_it = 1;
+ return 1;
+ }
+ hashcpy(cb->osha1, osha1);
+ hashcpy(cb->nsha1, nsha1);
+ if (cb->cnt > 0)
+ cb->cnt--;
+ return 0;
+}
+
+static int read_ref_at_ent_oldest(unsigned char *osha1, unsigned char *nsha1,
+ const char *email, unsigned long timestamp,
+ int tz, const char *message, void *cb_data)
+{
+ struct read_ref_at_cb *cb = cb_data;
+
+ if (cb->msg)
+ *cb->msg = xstrdup(message);
+ if (cb->cutoff_time)
+ *cb->cutoff_time = timestamp;
+ if (cb->cutoff_tz)
+ *cb->cutoff_tz = tz;
+ if (cb->cutoff_cnt)
+ *cb->cutoff_cnt = cb->reccnt;
+ hashcpy(cb->sha1, osha1);
+ if (is_null_sha1(cb->sha1))
+ hashcpy(cb->sha1, nsha1);
+ /* We just want the first entry */
+ return 1;
+}
+
+int read_ref_at(const char *refname, unsigned int flags, unsigned long at_time, int cnt,
+ unsigned char *sha1, char **msg,
+ unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt)
+{
+ struct read_ref_at_cb cb;
+
+ memset(&cb, 0, sizeof(cb));
+ cb.refname = refname;
+ cb.at_time = at_time;
+ cb.cnt = cnt;
+ cb.msg = msg;
+ cb.cutoff_time = cutoff_time;
+ cb.cutoff_tz = cutoff_tz;
+ cb.cutoff_cnt = cutoff_cnt;
+ cb.sha1 = sha1;
+
+ for_each_reflog_ent_reverse(refname, read_ref_at_ent, &cb);
+
+ if (!cb.reccnt) {
+ if (flags & GET_SHA1_QUIETLY)
+ exit(128);
+ else
+ die("Log for %s is empty.", refname);
+ }
+ if (cb.found_it)
+ return 0;
+
+ for_each_reflog_ent(refname, read_ref_at_ent_oldest, &cb);
+
+ return 1;
+}
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v4 08/26] refs.c: move the hidden refs functions to the common code
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
` (6 preceding siblings ...)
2015-10-15 19:46 ` [PATCH v4 07/26] refs.c: move read_ref_at to the common refs file David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-15 19:46 ` [PATCH v4 09/26] refs.c: move dwim and friend functions to the common refs code David Turner
` (17 subsequent siblings)
25 siblings, 0 replies; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: Ronnie Sahlberg, David Turner, Junio C Hamano
From: Ronnie Sahlberg <sahlberg@google.com>
Move the hidden refs functions to the refs.c file since these
functions do not contain any backend specific code.
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs-be-files.c | 51 ---------------------------------------------------
refs.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 51 insertions(+), 51 deletions(-)
diff --git a/refs-be-files.c b/refs-be-files.c
index 04c3206..dad23c7 100644
--- a/refs-be-files.c
+++ b/refs-be-files.c
@@ -4215,57 +4215,6 @@ char *shorten_unambiguous_ref(const char *refname, int strict)
return xstrdup(refname);
}
-static struct string_list *hide_refs;
-
-int parse_hide_refs_config(const char *var, const char *value, const char *section)
-{
- if (!strcmp("transfer.hiderefs", var) ||
- /* NEEDSWORK: use parse_config_key() once both are merged */
- (starts_with(var, section) && var[strlen(section)] == '.' &&
- !strcmp(var + strlen(section), ".hiderefs"))) {
- char *ref;
- int len;
-
- if (!value)
- return config_error_nonbool(var);
- ref = xstrdup(value);
- len = strlen(ref);
- while (len && ref[len - 1] == '/')
- ref[--len] = '\0';
- if (!hide_refs) {
- hide_refs = xcalloc(1, sizeof(*hide_refs));
- hide_refs->strdup_strings = 1;
- }
- string_list_append(hide_refs, ref);
- }
- return 0;
-}
-
-int ref_is_hidden(const char *refname)
-{
- int i;
-
- if (!hide_refs)
- return 0;
- for (i = hide_refs->nr - 1; i >= 0; i--) {
- const char *match = hide_refs->items[i].string;
- int neg = 0;
- int len;
-
- if (*match == '!') {
- neg = 1;
- match++;
- }
-
- if (!starts_with(refname, match))
- continue;
- len = strlen(match);
- if (!refname[len] || refname[len] == '/')
- return !neg;
- }
- return 0;
-}
-
struct expire_reflog_cb {
unsigned int flags;
reflog_expiry_should_prune_fn *should_prune_fn;
diff --git a/refs.c b/refs.c
index 8245118..6e5c8f8 100644
--- a/refs.c
+++ b/refs.c
@@ -292,3 +292,54 @@ int read_ref_at(const char *refname, unsigned int flags, unsigned long at_time,
return 1;
}
+
+static struct string_list *hide_refs;
+
+int parse_hide_refs_config(const char *var, const char *value, const char *section)
+{
+ if (!strcmp("transfer.hiderefs", var) ||
+ /* NEEDSWORK: use parse_config_key() once both are merged */
+ (starts_with(var, section) && var[strlen(section)] == '.' &&
+ !strcmp(var + strlen(section), ".hiderefs"))) {
+ char *ref;
+ int len;
+
+ if (!value)
+ return config_error_nonbool(var);
+ ref = xstrdup(value);
+ len = strlen(ref);
+ while (len && ref[len - 1] == '/')
+ ref[--len] = '\0';
+ if (!hide_refs) {
+ hide_refs = xcalloc(1, sizeof(*hide_refs));
+ hide_refs->strdup_strings = 1;
+ }
+ string_list_append(hide_refs, ref);
+ }
+ return 0;
+}
+
+int ref_is_hidden(const char *refname)
+{
+ int i;
+
+ if (!hide_refs)
+ return 0;
+ for (i = hide_refs->nr - 1; i >= 0; i--) {
+ const char *match = hide_refs->items[i].string;
+ int neg = 0;
+ int len;
+
+ if (*match == '!') {
+ neg = 1;
+ match++;
+ }
+
+ if (!starts_with(refname, match))
+ continue;
+ len = strlen(match);
+ if (!refname[len] || refname[len] == '/')
+ return !neg;
+ }
+ return 0;
+}
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v4 09/26] refs.c: move dwim and friend functions to the common refs code
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
` (7 preceding siblings ...)
2015-10-15 19:46 ` [PATCH v4 08/26] refs.c: move the hidden refs functions to the common code David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-15 19:46 ` [PATCH v4 10/26] refs.c: move warn_if_dangling_symref* to the common code David Turner
` (16 subsequent siblings)
25 siblings, 0 replies; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: Ronnie Sahlberg, David Turner, Junio C Hamano
From: Ronnie Sahlberg <sahlberg@google.com>
These functions do not contain any backend specific code so we move
them to the common code and share across all backends.
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs-be-files.c | 203 --------------------------------------------------------
refs.c | 203 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 203 insertions(+), 203 deletions(-)
diff --git a/refs-be-files.c b/refs-be-files.c
index dad23c7..3609fb7 100644
--- a/refs-be-files.c
+++ b/refs-be-files.c
@@ -2247,30 +2247,6 @@ const char *prettify_refname(const char *name)
0);
}
-static const char *ref_rev_parse_rules[] = {
- "%.*s",
- "refs/%.*s",
- "refs/tags/%.*s",
- "refs/heads/%.*s",
- "refs/remotes/%.*s",
- "refs/remotes/%.*s/HEAD",
- NULL
-};
-
-int refname_match(const char *abbrev_name, const char *full_name)
-{
- const char **p;
- const int abbrev_name_len = strlen(abbrev_name);
-
- for (p = ref_rev_parse_rules; *p; p++) {
- if (!strcmp(full_name, mkpath(*p, abbrev_name_len, abbrev_name))) {
- return 1;
- }
- }
-
- return 0;
-}
-
static void unlock_ref(struct ref_lock *lock)
{
/* Do not free lock->lk -- atexit() still looks at them */
@@ -2323,92 +2299,6 @@ static int remove_empty_directories(struct strbuf *path)
}
/*
- * *string and *len will only be substituted, and *string returned (for
- * later free()ing) if the string passed in is a magic short-hand form
- * to name a branch.
- */
-static char *substitute_branch_name(const char **string, int *len)
-{
- struct strbuf buf = STRBUF_INIT;
- int ret = interpret_branch_name(*string, *len, &buf);
-
- if (ret == *len) {
- size_t size;
- *string = strbuf_detach(&buf, &size);
- *len = size;
- return (char *)*string;
- }
-
- return NULL;
-}
-
-int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
-{
- char *last_branch = substitute_branch_name(&str, &len);
- const char **p, *r;
- int refs_found = 0;
-
- *ref = NULL;
- for (p = ref_rev_parse_rules; *p; p++) {
- char fullref[PATH_MAX];
- unsigned char sha1_from_ref[20];
- unsigned char *this_result;
- int flag;
-
- this_result = refs_found ? sha1_from_ref : sha1;
- mksnpath(fullref, sizeof(fullref), *p, len, str);
- r = resolve_ref_unsafe(fullref, RESOLVE_REF_READING,
- this_result, &flag);
- if (r) {
- if (!refs_found++)
- *ref = xstrdup(r);
- if (!warn_ambiguous_refs)
- break;
- } else if ((flag & REF_ISSYMREF) && strcmp(fullref, "HEAD")) {
- warning("ignoring dangling symref %s.", fullref);
- } else if ((flag & REF_ISBROKEN) && strchr(fullref, '/')) {
- warning("ignoring broken ref %s.", fullref);
- }
- }
- free(last_branch);
- return refs_found;
-}
-
-int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
-{
- char *last_branch = substitute_branch_name(&str, &len);
- const char **p;
- int logs_found = 0;
-
- *log = NULL;
- for (p = ref_rev_parse_rules; *p; p++) {
- unsigned char hash[20];
- char path[PATH_MAX];
- const char *ref, *it;
-
- mksnpath(path, sizeof(path), *p, len, str);
- ref = resolve_ref_unsafe(path, RESOLVE_REF_READING,
- hash, NULL);
- if (!ref)
- continue;
- if (reflog_exists(path))
- it = path;
- else if (strcmp(ref, path) && reflog_exists(ref))
- it = ref;
- else
- continue;
- if (!logs_found++) {
- *log = xstrdup(it);
- hashcpy(sha1, hash);
- }
- if (!warn_ambiguous_refs)
- break;
- }
- free(last_branch);
- return logs_found;
-}
-
-/*
* Locks a ref returning the lock on success and NULL on failure.
* On failure errno is set to something meaningful.
*/
@@ -4122,99 +4012,6 @@ cleanup:
return ret;
}
-char *shorten_unambiguous_ref(const char *refname, int strict)
-{
- int i;
- static char **scanf_fmts;
- static int nr_rules;
- char *short_name;
-
- if (!nr_rules) {
- /*
- * Pre-generate scanf formats from ref_rev_parse_rules[].
- * Generate a format suitable for scanf from a
- * ref_rev_parse_rules rule by interpolating "%s" at the
- * location of the "%.*s".
- */
- size_t total_len = 0;
- size_t offset = 0;
-
- /* the rule list is NULL terminated, count them first */
- for (nr_rules = 0; ref_rev_parse_rules[nr_rules]; nr_rules++)
- /* -2 for strlen("%.*s") - strlen("%s"); +1 for NUL */
- total_len += strlen(ref_rev_parse_rules[nr_rules]) - 2 + 1;
-
- scanf_fmts = xmalloc(nr_rules * sizeof(char *) + total_len);
-
- offset = 0;
- for (i = 0; i < nr_rules; i++) {
- assert(offset < total_len);
- scanf_fmts[i] = (char *)&scanf_fmts[nr_rules] + offset;
- offset += snprintf(scanf_fmts[i], total_len - offset,
- ref_rev_parse_rules[i], 2, "%s") + 1;
- }
- }
-
- /* bail out if there are no rules */
- if (!nr_rules)
- return xstrdup(refname);
-
- /* buffer for scanf result, at most refname must fit */
- short_name = xstrdup(refname);
-
- /* skip first rule, it will always match */
- for (i = nr_rules - 1; i > 0 ; --i) {
- int j;
- int rules_to_fail = i;
- int short_name_len;
-
- if (1 != sscanf(refname, scanf_fmts[i], short_name))
- continue;
-
- short_name_len = strlen(short_name);
-
- /*
- * in strict mode, all (except the matched one) rules
- * must fail to resolve to a valid non-ambiguous ref
- */
- if (strict)
- rules_to_fail = nr_rules;
-
- /*
- * check if the short name resolves to a valid ref,
- * but use only rules prior to the matched one
- */
- for (j = 0; j < rules_to_fail; j++) {
- const char *rule = ref_rev_parse_rules[j];
- char refname[PATH_MAX];
-
- /* skip matched rule */
- if (i == j)
- continue;
-
- /*
- * the short name is ambiguous, if it resolves
- * (with this previous rule) to a valid ref
- * read_ref() returns 0 on success
- */
- mksnpath(refname, sizeof(refname),
- rule, short_name_len, short_name);
- if (ref_exists(refname))
- break;
- }
-
- /*
- * short name is non-ambiguous if all previous rules
- * haven't resolved to a valid ref
- */
- if (j == rules_to_fail)
- return short_name;
- }
-
- free(short_name);
- return xstrdup(refname);
-}
-
struct expire_reflog_cb {
unsigned int flags;
reflog_expiry_should_prune_fn *should_prune_fn;
diff --git a/refs.c b/refs.c
index 6e5c8f8..53296e9 100644
--- a/refs.c
+++ b/refs.c
@@ -343,3 +343,206 @@ int ref_is_hidden(const char *refname)
}
return 0;
}
+
+static const char *ref_rev_parse_rules[] = {
+ "%.*s",
+ "refs/%.*s",
+ "refs/tags/%.*s",
+ "refs/heads/%.*s",
+ "refs/remotes/%.*s",
+ "refs/remotes/%.*s/HEAD",
+ NULL
+};
+
+int refname_match(const char *abbrev_name, const char *full_name)
+{
+ const char **p;
+ const int abbrev_name_len = strlen(abbrev_name);
+
+ for (p = ref_rev_parse_rules; *p; p++) {
+ if (!strcmp(full_name, mkpath(*p, abbrev_name_len, abbrev_name))) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * *string and *len will only be substituted, and *string returned (for
+ * later free()ing) if the string passed in is a magic short-hand form
+ * to name a branch.
+ */
+static char *substitute_branch_name(const char **string, int *len)
+{
+ struct strbuf buf = STRBUF_INIT;
+ int ret = interpret_branch_name(*string, *len, &buf);
+
+ if (ret == *len) {
+ size_t size;
+ *string = strbuf_detach(&buf, &size);
+ *len = size;
+ return (char *)*string;
+ }
+
+ return NULL;
+}
+
+int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
+{
+ char *last_branch = substitute_branch_name(&str, &len);
+ const char **p, *r;
+ int refs_found = 0;
+
+ *ref = NULL;
+ for (p = ref_rev_parse_rules; *p; p++) {
+ char fullref[PATH_MAX];
+ unsigned char sha1_from_ref[20];
+ unsigned char *this_result;
+ int flag;
+
+ this_result = refs_found ? sha1_from_ref : sha1;
+ mksnpath(fullref, sizeof(fullref), *p, len, str);
+ r = resolve_ref_unsafe(fullref, RESOLVE_REF_READING,
+ this_result, &flag);
+ if (r) {
+ if (!refs_found++)
+ *ref = xstrdup(r);
+ if (!warn_ambiguous_refs)
+ break;
+ } else if ((flag & REF_ISSYMREF) && strcmp(fullref, "HEAD")) {
+ warning("ignoring dangling symref %s.", fullref);
+ } else if ((flag & REF_ISBROKEN) && strchr(fullref, '/')) {
+ warning("ignoring broken ref %s.", fullref);
+ }
+ }
+ free(last_branch);
+ return refs_found;
+}
+
+int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
+{
+ char *last_branch = substitute_branch_name(&str, &len);
+ const char **p;
+ int logs_found = 0;
+
+ *log = NULL;
+ for (p = ref_rev_parse_rules; *p; p++) {
+ unsigned char hash[20];
+ char path[PATH_MAX];
+ const char *ref, *it;
+
+ mksnpath(path, sizeof(path), *p, len, str);
+ ref = resolve_ref_unsafe(path, RESOLVE_REF_READING,
+ hash, NULL);
+ if (!ref)
+ continue;
+ if (reflog_exists(path))
+ it = path;
+ else if (strcmp(ref, path) && reflog_exists(ref))
+ it = ref;
+ else
+ continue;
+ if (!logs_found++) {
+ *log = xstrdup(it);
+ hashcpy(sha1, hash);
+ }
+ if (!warn_ambiguous_refs)
+ break;
+ }
+ free(last_branch);
+ return logs_found;
+}
+
+char *shorten_unambiguous_ref(const char *refname, int strict)
+{
+ int i;
+ static char **scanf_fmts;
+ static int nr_rules;
+ char *short_name;
+
+ if (!nr_rules) {
+ /*
+ * Pre-generate scanf formats from ref_rev_parse_rules[].
+ * Generate a format suitable for scanf from a
+ * ref_rev_parse_rules rule by interpolating "%s" at the
+ * location of the "%.*s".
+ */
+ size_t total_len = 0;
+ size_t offset = 0;
+
+ /* the rule list is NULL terminated, count them first */
+ for (nr_rules = 0; ref_rev_parse_rules[nr_rules]; nr_rules++)
+ /* -2 for strlen("%.*s") - strlen("%s"); +1 for NUL */
+ total_len += strlen(ref_rev_parse_rules[nr_rules]) - 2 + 1;
+
+ scanf_fmts = xmalloc(nr_rules * sizeof(char *) + total_len);
+
+ offset = 0;
+ for (i = 0; i < nr_rules; i++) {
+ assert(offset < total_len);
+ scanf_fmts[i] = (char *)&scanf_fmts[nr_rules] + offset;
+ offset += snprintf(scanf_fmts[i], total_len - offset,
+ ref_rev_parse_rules[i], 2, "%s") + 1;
+ }
+ }
+
+ /* bail out if there are no rules */
+ if (!nr_rules)
+ return xstrdup(refname);
+
+ /* buffer for scanf result, at most refname must fit */
+ short_name = xstrdup(refname);
+
+ /* skip first rule, it will always match */
+ for (i = nr_rules - 1; i > 0 ; --i) {
+ int j;
+ int rules_to_fail = i;
+ int short_name_len;
+
+ if (1 != sscanf(refname, scanf_fmts[i], short_name))
+ continue;
+
+ short_name_len = strlen(short_name);
+
+ /*
+ * in strict mode, all (except the matched one) rules
+ * must fail to resolve to a valid non-ambiguous ref
+ */
+ if (strict)
+ rules_to_fail = nr_rules;
+
+ /*
+ * check if the short name resolves to a valid ref,
+ * but use only rules prior to the matched one
+ */
+ for (j = 0; j < rules_to_fail; j++) {
+ const char *rule = ref_rev_parse_rules[j];
+ char refname[PATH_MAX];
+
+ /* skip matched rule */
+ if (i == j)
+ continue;
+
+ /*
+ * the short name is ambiguous, if it resolves
+ * (with this previous rule) to a valid ref
+ * read_ref() returns 0 on success
+ */
+ mksnpath(refname, sizeof(refname),
+ rule, short_name_len, short_name);
+ if (ref_exists(refname))
+ break;
+ }
+
+ /*
+ * short name is non-ambiguous if all previous rules
+ * haven't resolved to a valid ref
+ */
+ if (j == rules_to_fail)
+ return short_name;
+ }
+
+ free(short_name);
+ return xstrdup(refname);
+}
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v4 10/26] refs.c: move warn_if_dangling_symref* to the common code
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
` (8 preceding siblings ...)
2015-10-15 19:46 ` [PATCH v4 09/26] refs.c: move dwim and friend functions to the common refs code David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-15 19:46 ` [PATCH v4 11/26] refs.c: move read_ref, read_ref_full and ref_exists " David Turner
` (15 subsequent siblings)
25 siblings, 0 replies; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: Ronnie Sahlberg, David Turner, Junio C Hamano
From: Ronnie Sahlberg <sahlberg@google.com>
These functions do not use any backend specific code so we move
them to the common code.
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs-be-files.c | 52 ----------------------------------------------------
refs.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 52 insertions(+), 52 deletions(-)
diff --git a/refs-be-files.c b/refs-be-files.c
index 3609fb7..9c53f54 100644
--- a/refs-be-files.c
+++ b/refs-be-files.c
@@ -1944,58 +1944,6 @@ int peel_ref(const char *refname, unsigned char *sha1)
return peel_object(base, sha1);
}
-struct warn_if_dangling_data {
- FILE *fp;
- const char *refname;
- const struct string_list *refnames;
- const char *msg_fmt;
-};
-
-static int warn_if_dangling_symref(const char *refname, const struct object_id *oid,
- int flags, void *cb_data)
-{
- struct warn_if_dangling_data *d = cb_data;
- const char *resolves_to;
- struct object_id junk;
-
- if (!(flags & REF_ISSYMREF))
- return 0;
-
- resolves_to = resolve_ref_unsafe(refname, 0, junk.hash, NULL);
- if (!resolves_to
- || (d->refname
- ? strcmp(resolves_to, d->refname)
- : !string_list_has_string(d->refnames, resolves_to))) {
- return 0;
- }
-
- fprintf(d->fp, d->msg_fmt, refname);
- fputc('\n', d->fp);
- return 0;
-}
-
-void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname)
-{
- struct warn_if_dangling_data data;
-
- data.fp = fp;
- data.refname = refname;
- data.refnames = NULL;
- data.msg_fmt = msg_fmt;
- for_each_rawref(warn_if_dangling_symref, &data);
-}
-
-void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, const struct string_list *refnames)
-{
- struct warn_if_dangling_data data;
-
- data.fp = fp;
- data.refname = NULL;
- data.refnames = refnames;
- data.msg_fmt = msg_fmt;
- for_each_rawref(warn_if_dangling_symref, &data);
-}
-
/*
* Call fn for each reference in the specified ref_cache, omitting
* references not in the containing_dir of base. fn is called for all
diff --git a/refs.c b/refs.c
index 53296e9..fab7603 100644
--- a/refs.c
+++ b/refs.c
@@ -546,3 +546,55 @@ char *shorten_unambiguous_ref(const char *refname, int strict)
free(short_name);
return xstrdup(refname);
}
+
+struct warn_if_dangling_data {
+ FILE *fp;
+ const char *refname;
+ const struct string_list *refnames;
+ const char *msg_fmt;
+};
+
+static int warn_if_dangling_symref(const char *refname, const struct object_id *oid,
+ int flags, void *cb_data)
+{
+ struct warn_if_dangling_data *d = cb_data;
+ const char *resolves_to;
+ struct object_id junk;
+
+ if (!(flags & REF_ISSYMREF))
+ return 0;
+
+ resolves_to = resolve_ref_unsafe(refname, 0, junk.hash, NULL);
+ if (!resolves_to
+ || (d->refname
+ ? strcmp(resolves_to, d->refname)
+ : !string_list_has_string(d->refnames, resolves_to))) {
+ return 0;
+ }
+
+ fprintf(d->fp, d->msg_fmt, refname);
+ fputc('\n', d->fp);
+ return 0;
+}
+
+void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname)
+{
+ struct warn_if_dangling_data data;
+
+ data.fp = fp;
+ data.refname = refname;
+ data.refnames = NULL;
+ data.msg_fmt = msg_fmt;
+ for_each_rawref(warn_if_dangling_symref, &data);
+}
+
+void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, const struct string_list *refnames)
+{
+ struct warn_if_dangling_data data;
+
+ data.fp = fp;
+ data.refname = NULL;
+ data.refnames = refnames;
+ data.msg_fmt = msg_fmt;
+ for_each_rawref(warn_if_dangling_symref, &data);
+}
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v4 11/26] refs.c: move read_ref, read_ref_full and ref_exists to the common code
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
` (9 preceding siblings ...)
2015-10-15 19:46 ` [PATCH v4 10/26] refs.c: move warn_if_dangling_symref* to the common code David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-15 19:46 ` [PATCH v4 12/26] refs.c: move resolve_refdup to common David Turner
` (14 subsequent siblings)
25 siblings, 0 replies; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: Ronnie Sahlberg, David Turner, Junio C Hamano
From: Ronnie Sahlberg <sahlberg@google.com>
These functions do not depend on the backend implementation so we
move them to the common code.
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs-be-files.c | 18 ------------------
refs.c | 18 ++++++++++++++++++
2 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/refs-be-files.c b/refs-be-files.c
index 9c53f54..728751a 100644
--- a/refs-be-files.c
+++ b/refs-be-files.c
@@ -1791,24 +1791,6 @@ struct ref_filter {
void *cb_data;
};
-int read_ref_full(const char *refname, int resolve_flags, unsigned char *sha1, int *flags)
-{
- if (resolve_ref_unsafe(refname, resolve_flags, sha1, flags))
- return 0;
- return -1;
-}
-
-int read_ref(const char *refname, unsigned char *sha1)
-{
- return read_ref_full(refname, RESOLVE_REF_READING, sha1, NULL);
-}
-
-int ref_exists(const char *refname)
-{
- unsigned char sha1[20];
- return !!resolve_ref_unsafe(refname, RESOLVE_REF_READING, sha1, NULL);
-}
-
static int filter_refs(const char *refname, const struct object_id *oid,
int flags, void *data)
{
diff --git a/refs.c b/refs.c
index fab7603..8a619a6 100644
--- a/refs.c
+++ b/refs.c
@@ -598,3 +598,21 @@ void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, const struct string_li
data.msg_fmt = msg_fmt;
for_each_rawref(warn_if_dangling_symref, &data);
}
+
+int read_ref_full(const char *refname, int resolve_flags, unsigned char *sha1, int *flags)
+{
+ if (resolve_ref_unsafe(refname, resolve_flags, sha1, flags))
+ return 0;
+ return -1;
+}
+
+int read_ref(const char *refname, unsigned char *sha1)
+{
+ return read_ref_full(refname, RESOLVE_REF_READING, sha1, NULL);
+}
+
+int ref_exists(const char *refname)
+{
+ unsigned char sha1[20];
+ return !!resolve_ref_unsafe(refname, RESOLVE_REF_READING, sha1, NULL);
+}
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v4 12/26] refs.c: move resolve_refdup to common
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
` (10 preceding siblings ...)
2015-10-15 19:46 ` [PATCH v4 11/26] refs.c: move read_ref, read_ref_full and ref_exists " David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-15 19:46 ` [PATCH v4 13/26] refs.c: move check_refname_format to the common code David Turner
` (13 subsequent siblings)
25 siblings, 0 replies; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: Ronnie Sahlberg, David Turner, Junio C Hamano
From: Ronnie Sahlberg <sahlberg@google.com>
This function can be shared across all refs backends so move it
to the common code.
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs-be-files.c | 7 -------
refs.c | 7 +++++++
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/refs-be-files.c b/refs-be-files.c
index 728751a..589e10d 100644
--- a/refs-be-files.c
+++ b/refs-be-files.c
@@ -1777,13 +1777,6 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
return ret;
}
-char *resolve_refdup(const char *refname, int resolve_flags,
- unsigned char *sha1, int *flags)
-{
- return xstrdup_or_null(resolve_ref_unsafe(refname, resolve_flags,
- sha1, flags));
-}
-
/* The argument to filter_refs */
struct ref_filter {
const char *pattern;
diff --git a/refs.c b/refs.c
index 8a619a6..fcd5ddd 100644
--- a/refs.c
+++ b/refs.c
@@ -616,3 +616,10 @@ int ref_exists(const char *refname)
unsigned char sha1[20];
return !!resolve_ref_unsafe(refname, RESOLVE_REF_READING, sha1, NULL);
}
+
+char *resolve_refdup(const char *refname, int resolve_flags,
+ unsigned char *sha1, int *flags)
+{
+ return xstrdup_or_null(resolve_ref_unsafe(refname, resolve_flags,
+ sha1, flags));
+}
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v4 13/26] refs.c: move check_refname_format to the common code
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
` (11 preceding siblings ...)
2015-10-15 19:46 ` [PATCH v4 12/26] refs.c: move resolve_refdup to common David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-15 19:46 ` [PATCH v4 14/26] refs.c: move is_branch " David Turner
` (12 subsequent siblings)
25 siblings, 0 replies; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: Ronnie Sahlberg, David Turner, Junio C Hamano
From: Ronnie Sahlberg <sahlberg@google.com>
This function does not contain any backend specific code so we
move it to the common code.
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs-be-files.c | 109 --------------------------------------------------------
refs.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 109 insertions(+), 109 deletions(-)
diff --git a/refs-be-files.c b/refs-be-files.c
index 589e10d..345bee7 100644
--- a/refs-be-files.c
+++ b/refs-be-files.c
@@ -14,27 +14,6 @@ struct ref_lock {
};
/*
- * How to handle various characters in refnames:
- * 0: An acceptable character for refs
- * 1: End-of-component
- * 2: ., look for a preceding . to reject .. in refs
- * 3: {, look for a preceding @ to reject @{ in refs
- * 4: A bad character: ASCII control characters, and
- * ":", "?", "[", "\", "^", "~", SP, or TAB
- * 5: *, reject unless REFNAME_REFSPEC_PATTERN is set
- */
-static unsigned char refname_disposition[256] = {
- 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 2, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 4,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 4, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 4, 4
-};
-
-/*
* Flag passed to lock_ref_sha1_basic() telling it to tolerate broken
* refs (i.e., because the reference is about to be deleted anyway).
*/
@@ -69,94 +48,6 @@ static unsigned char refname_disposition[256] = {
* value to ref_update::flags
*/
-/*
- * Try to read one refname component from the front of refname.
- * Return the length of the component found, or -1 if the component is
- * not legal. It is legal if it is something reasonable to have under
- * ".git/refs/"; We do not like it if:
- *
- * - any path component of it begins with ".", or
- * - it has double dots "..", or
- * - it has ASCII control characters, or
- * - it has ":", "?", "[", "\", "^", "~", SP, or TAB anywhere, or
- * - it has "*" anywhere unless REFNAME_REFSPEC_PATTERN is set, or
- * - it ends with a "/", or
- * - it ends with ".lock", or
- * - it contains a "@{" portion
- */
-static int check_refname_component(const char *refname, int *flags)
-{
- const char *cp;
- char last = '\0';
-
- for (cp = refname; ; cp++) {
- int ch = *cp & 255;
- unsigned char disp = refname_disposition[ch];
- switch (disp) {
- case 1:
- goto out;
- case 2:
- if (last == '.')
- return -1; /* Refname contains "..". */
- break;
- case 3:
- if (last == '@')
- return -1; /* Refname contains "@{". */
- break;
- case 4:
- return -1;
- case 5:
- if (!(*flags & REFNAME_REFSPEC_PATTERN))
- return -1; /* refspec can't be a pattern */
-
- /*
- * Unset the pattern flag so that we only accept
- * a single asterisk for one side of refspec.
- */
- *flags &= ~ REFNAME_REFSPEC_PATTERN;
- break;
- }
- last = ch;
- }
-out:
- if (cp == refname)
- return 0; /* Component has zero length. */
- if (refname[0] == '.')
- return -1; /* Component starts with '.'. */
- if (cp - refname >= LOCK_SUFFIX_LEN &&
- !memcmp(cp - LOCK_SUFFIX_LEN, LOCK_SUFFIX, LOCK_SUFFIX_LEN))
- return -1; /* Refname ends with ".lock". */
- return cp - refname;
-}
-
-int check_refname_format(const char *refname, int flags)
-{
- int component_len, component_count = 0;
-
- if (!strcmp(refname, "@"))
- /* Refname is a single character '@'. */
- return -1;
-
- while (1) {
- /* We are at the start of a path component. */
- component_len = check_refname_component(refname, &flags);
- if (component_len <= 0)
- return -1;
-
- component_count++;
- if (refname[component_len] == '\0')
- break;
- /* Skip to next component. */
- refname += component_len + 1;
- }
-
- if (refname[component_len - 1] == '.')
- return -1; /* Refname ends with '.'. */
- if (!(flags & REFNAME_ALLOW_ONELEVEL) && component_count < 2)
- return -1; /* Refname has only one component. */
- return 0;
-}
-
struct ref_entry;
/*
diff --git a/refs.c b/refs.c
index fcd5ddd..d79ba82 100644
--- a/refs.c
+++ b/refs.c
@@ -623,3 +623,112 @@ char *resolve_refdup(const char *refname, int resolve_flags,
return xstrdup_or_null(resolve_ref_unsafe(refname, resolve_flags,
sha1, flags));
}
+
+/*
+ * How to handle various characters in refnames:
+ * 0: An acceptable character for refs
+ * 1: End-of-component
+ * 2: ., look for a preceding . to reject .. in refs
+ * 3: {, look for a preceding @ to reject @{ in refs
+ * 4: A bad character: ASCII control characters, and
+ * ":", "?", "[", "\", "^", "~", SP, or TAB
+ * 5: *, reject unless REFNAME_REFSPEC_PATTERN is set
+ */
+static unsigned char refname_disposition[256] = {
+ 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 2, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 4,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 4, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 4, 4
+};
+
+/*
+ * Try to read one refname component from the front of refname.
+ * Return the length of the component found, or -1 if the component is
+ * not legal. It is legal if it is something reasonable to have under
+ * ".git/refs/"; We do not like it if:
+ *
+ * - any path component of it begins with ".", or
+ * - it has double dots "..", or
+ * - it has ASCII control characters, or
+ * - it has ":", "?", "[", "\", "^", "~", SP, or TAB anywhere, or
+ * - it has "*" anywhere unless REFNAME_REFSPEC_PATTERN is set, or
+ * - it ends with a "/", or
+ * - it ends with ".lock", or
+ * - it contains a "@{" portion
+ */
+static int check_refname_component(const char *refname, int *flags)
+{
+ const char *cp;
+ char last = '\0';
+
+ for (cp = refname; ; cp++) {
+ int ch = *cp & 255;
+ unsigned char disp = refname_disposition[ch];
+ switch (disp) {
+ case 1:
+ goto out;
+ case 2:
+ if (last == '.')
+ return -1; /* Refname contains "..". */
+ break;
+ case 3:
+ if (last == '@')
+ return -1; /* Refname contains "@{". */
+ break;
+ case 4:
+ return -1;
+ case 5:
+ if (!(*flags & REFNAME_REFSPEC_PATTERN))
+ return -1; /* refspec can't be a pattern */
+
+ /*
+ * Unset the pattern flag so that we only accept
+ * a single asterisk for one side of refspec.
+ */
+ *flags &= ~ REFNAME_REFSPEC_PATTERN;
+ break;
+ }
+ last = ch;
+ }
+out:
+ if (cp == refname)
+ return 0; /* Component has zero length. */
+ if (refname[0] == '.')
+ return -1; /* Component starts with '.'. */
+ if (cp - refname >= LOCK_SUFFIX_LEN &&
+ !memcmp(cp - LOCK_SUFFIX_LEN, LOCK_SUFFIX, LOCK_SUFFIX_LEN))
+ return -1; /* Refname ends with ".lock". */
+ return cp - refname;
+}
+
+int check_refname_format(const char *refname, int flags)
+{
+ int component_len, component_count = 0;
+
+ if (!strcmp(refname, "@"))
+ /* Refname is a single character '@'. */
+ return -1;
+
+ while (1) {
+ /* We are at the start of a path component. */
+ component_len = check_refname_component(refname, &flags);
+ if (component_len <= 0)
+ return -1;
+
+ component_count++;
+ if (refname[component_len] == '\0')
+ break;
+ /* Skip to next component. */
+ refname += component_len + 1;
+ }
+
+ if (refname[component_len - 1] == '.')
+ return -1; /* Refname ends with '.'. */
+ if (!(flags & REFNAME_ALLOW_ONELEVEL) && component_count < 2)
+ return -1; /* Refname has only one component. */
+ return 0;
+}
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v4 14/26] refs.c: move is_branch to the common code
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
` (12 preceding siblings ...)
2015-10-15 19:46 ` [PATCH v4 13/26] refs.c: move check_refname_format to the common code David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-15 19:46 ` [PATCH v4 15/26] refs.c: move prettify_refname " David Turner
` (11 subsequent siblings)
25 siblings, 0 replies; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: Ronnie Sahlberg, David Turner, Junio C Hamano
From: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs-be-files.c | 5 -----
refs.c | 5 +++++
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/refs-be-files.c b/refs-be-files.c
index 345bee7..5c6c743 100644
--- a/refs-be-files.c
+++ b/refs-be-files.c
@@ -3003,11 +3003,6 @@ static int log_ref_write(const char *refname, const unsigned char *old_sha1,
return ret;
}
-int is_branch(const char *refname)
-{
- return !strcmp(refname, "HEAD") || starts_with(refname, "refs/heads/");
-}
-
/*
* Write sha1 into the open lockfile, then close the lockfile. On
* errors, rollback the lockfile, fill in *err and
diff --git a/refs.c b/refs.c
index d79ba82..f2f8052 100644
--- a/refs.c
+++ b/refs.c
@@ -732,3 +732,8 @@ int check_refname_format(const char *refname, int flags)
return -1; /* Refname has only one component. */
return 0;
}
+
+int is_branch(const char *refname)
+{
+ return !strcmp(refname, "HEAD") || starts_with(refname, "refs/heads/");
+}
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v4 15/26] refs.c: move prettify_refname to the common code
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
` (13 preceding siblings ...)
2015-10-15 19:46 ` [PATCH v4 14/26] refs.c: move is_branch " David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-15 19:46 ` [PATCH v4 16/26] refs.c: move ref iterators " David Turner
` (10 subsequent siblings)
25 siblings, 0 replies; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: Ronnie Sahlberg, Junio C Hamano
From: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs-be-files.c | 9 ---------
refs.c | 9 +++++++++
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/refs-be-files.c b/refs-be-files.c
index 5c6c743..c8b44ab 100644
--- a/refs-be-files.c
+++ b/refs-be-files.c
@@ -2052,15 +2052,6 @@ int for_each_rawref(each_ref_fn fn, void *cb_data)
DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
}
-const char *prettify_refname(const char *name)
-{
- return name + (
- starts_with(name, "refs/heads/") ? 11 :
- starts_with(name, "refs/tags/") ? 10 :
- starts_with(name, "refs/remotes/") ? 13 :
- 0);
-}
-
static void unlock_ref(struct ref_lock *lock)
{
/* Do not free lock->lk -- atexit() still looks at them */
diff --git a/refs.c b/refs.c
index f2f8052..642a2ab 100644
--- a/refs.c
+++ b/refs.c
@@ -737,3 +737,12 @@ int is_branch(const char *refname)
{
return !strcmp(refname, "HEAD") || starts_with(refname, "refs/heads/");
}
+
+const char *prettify_refname(const char *name)
+{
+ return name + (
+ starts_with(name, "refs/heads/") ? 11 :
+ starts_with(name, "refs/tags/") ? 10 :
+ starts_with(name, "refs/remotes/") ? 13 :
+ 0);
+}
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v4 16/26] refs.c: move ref iterators to the common code
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
` (14 preceding siblings ...)
2015-10-15 19:46 ` [PATCH v4 15/26] refs.c: move prettify_refname " David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-15 19:46 ` [PATCH v4 17/26] refs.c: move head_ref_namespaced " David Turner
` (9 subsequent siblings)
25 siblings, 0 replies; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: Ronnie Sahlberg, Junio C Hamano
From: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs-be-files.c | 82 ---------------------------------------------------------
refs.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 81 insertions(+), 82 deletions(-)
diff --git a/refs-be-files.c b/refs-be-files.c
index c8b44ab..14319cb 100644
--- a/refs-be-files.c
+++ b/refs-be-files.c
@@ -1668,23 +1668,6 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
return ret;
}
-/* The argument to filter_refs */
-struct ref_filter {
- const char *pattern;
- each_ref_fn *fn;
- void *cb_data;
-};
-
-static int filter_refs(const char *refname, const struct object_id *oid,
- int flags, void *data)
-{
- struct ref_filter *filter = (struct ref_filter *)data;
-
- if (wildmatch(filter->pattern, refname, 0, NULL))
- return 0;
- return filter->fn(refname, oid, flags, filter->cb_data);
-}
-
enum peel_status {
/* object was peeled successfully: */
PEEL_PEELED = 0,
@@ -1950,37 +1933,6 @@ int for_each_ref_in_submodule(const char *submodule, const char *prefix,
{
return do_for_each_ref(get_ref_cache(submodule), prefix, fn, strlen(prefix), 0, cb_data);
}
-
-int for_each_tag_ref(each_ref_fn fn, void *cb_data)
-{
- return for_each_ref_in("refs/tags/", fn, cb_data);
-}
-
-int for_each_tag_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
-{
- return for_each_ref_in_submodule(submodule, "refs/tags/", fn, cb_data);
-}
-
-int for_each_branch_ref(each_ref_fn fn, void *cb_data)
-{
- return for_each_ref_in("refs/heads/", fn, cb_data);
-}
-
-int for_each_branch_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
-{
- return for_each_ref_in_submodule(submodule, "refs/heads/", fn, cb_data);
-}
-
-int for_each_remote_ref(each_ref_fn fn, void *cb_data)
-{
- return for_each_ref_in("refs/remotes/", fn, cb_data);
-}
-
-int for_each_remote_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
-{
- return for_each_ref_in_submodule(submodule, "refs/remotes/", fn, cb_data);
-}
-
int for_each_replace_ref(each_ref_fn fn, void *cb_data)
{
return do_for_each_ref(&ref_cache, git_replace_ref_base, fn,
@@ -2012,40 +1964,6 @@ int for_each_namespaced_ref(each_ref_fn fn, void *cb_data)
return ret;
}
-int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,
- const char *prefix, void *cb_data)
-{
- struct strbuf real_pattern = STRBUF_INIT;
- struct ref_filter filter;
- int ret;
-
- if (!prefix && !starts_with(pattern, "refs/"))
- strbuf_addstr(&real_pattern, "refs/");
- else if (prefix)
- strbuf_addstr(&real_pattern, prefix);
- strbuf_addstr(&real_pattern, pattern);
-
- if (!has_glob_specials(pattern)) {
- /* Append implied '/' '*' if not present. */
- strbuf_complete(&real_pattern, '/');
- /* No need to check for '*', there is none. */
- strbuf_addch(&real_pattern, '*');
- }
-
- filter.pattern = real_pattern.buf;
- filter.fn = fn;
- filter.cb_data = cb_data;
- ret = for_each_ref(filter_refs, &filter);
-
- strbuf_release(&real_pattern);
- return ret;
-}
-
-int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data)
-{
- return for_each_glob_ref_in(fn, pattern, NULL, cb_data);
-}
-
int for_each_rawref(each_ref_fn fn, void *cb_data)
{
return do_for_each_ref(&ref_cache, "", fn, 0,
diff --git a/refs.c b/refs.c
index 642a2ab..f7aa9b3 100644
--- a/refs.c
+++ b/refs.c
@@ -746,3 +746,84 @@ const char *prettify_refname(const char *name)
starts_with(name, "refs/remotes/") ? 13 :
0);
}
+
+/* The argument to filter_refs */
+struct ref_filter {
+ const char *pattern;
+ each_ref_fn *fn;
+ void *cb_data;
+};
+
+static int filter_refs(const char *refname, const struct object_id *oid, int flags,
+ void *data)
+{
+ struct ref_filter *filter = (struct ref_filter *)data;
+
+ if (wildmatch(filter->pattern, refname, 0, NULL))
+ return 0;
+ return filter->fn(refname, oid, flags, filter->cb_data);
+}
+
+int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,
+ const char *prefix, void *cb_data)
+{
+ struct strbuf real_pattern = STRBUF_INIT;
+ struct ref_filter filter;
+ int ret;
+
+ if (!prefix && !starts_with(pattern, "refs/"))
+ strbuf_addstr(&real_pattern, "refs/");
+ else if (prefix)
+ strbuf_addstr(&real_pattern, prefix);
+ strbuf_addstr(&real_pattern, pattern);
+
+ if (!has_glob_specials(pattern)) {
+ /* Append implied '/' '*' if not present. */
+ strbuf_complete(&real_pattern, '/');
+ /* No need to check for '*', there is none. */
+ strbuf_addch(&real_pattern, '*');
+ }
+
+ filter.pattern = real_pattern.buf;
+ filter.fn = fn;
+ filter.cb_data = cb_data;
+ ret = for_each_ref(filter_refs, &filter);
+
+ strbuf_release(&real_pattern);
+ return ret;
+}
+
+int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data)
+{
+ return for_each_glob_ref_in(fn, pattern, NULL, cb_data);
+}
+
+int for_each_tag_ref(each_ref_fn fn, void *cb_data)
+{
+ return for_each_ref_in("refs/tags/", fn, cb_data);
+}
+
+int for_each_tag_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
+{
+ return for_each_ref_in_submodule(submodule, "refs/tags/", fn, cb_data);
+}
+
+int for_each_branch_ref(each_ref_fn fn, void *cb_data)
+{
+ return for_each_ref_in("refs/heads/", fn, cb_data);
+}
+
+int for_each_branch_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
+{
+ return for_each_ref_in_submodule(submodule, "refs/heads/", fn, cb_data);
+}
+
+int for_each_remote_ref(each_ref_fn fn, void *cb_data)
+{
+ return for_each_ref_in("refs/remotes/", fn, cb_data);
+}
+
+int for_each_remote_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
+{
+ return for_each_ref_in_submodule(submodule, "refs/remotes/", fn, cb_data);
+}
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v4 17/26] refs.c: move head_ref_namespaced to the common code
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
` (15 preceding siblings ...)
2015-10-15 19:46 ` [PATCH v4 16/26] refs.c: move ref iterators " David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-15 19:46 ` [PATCH v4 18/26] refs: move transaction functions into " David Turner
` (8 subsequent siblings)
25 siblings, 0 replies; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: Ronnie Sahlberg, Junio C Hamano
From: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs-be-files.c | 15 ---------------
refs.c | 15 +++++++++++++++
2 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/refs-be-files.c b/refs-be-files.c
index 14319cb..ffc3813 100644
--- a/refs-be-files.c
+++ b/refs-be-files.c
@@ -1939,21 +1939,6 @@ int for_each_replace_ref(each_ref_fn fn, void *cb_data)
strlen(git_replace_ref_base), 0, cb_data);
}
-int head_ref_namespaced(each_ref_fn fn, void *cb_data)
-{
- struct strbuf buf = STRBUF_INIT;
- int ret = 0;
- struct object_id oid;
- int flag;
-
- strbuf_addf(&buf, "%sHEAD", get_git_namespace());
- if (!read_ref_full(buf.buf, RESOLVE_REF_READING, oid.hash, &flag))
- ret = fn(buf.buf, &oid, flag, cb_data);
- strbuf_release(&buf);
-
- return ret;
-}
-
int for_each_namespaced_ref(each_ref_fn fn, void *cb_data)
{
struct strbuf buf = STRBUF_INIT;
diff --git a/refs.c b/refs.c
index f7aa9b3..ae518a2 100644
--- a/refs.c
+++ b/refs.c
@@ -827,3 +827,18 @@ int for_each_remote_ref_submodule(const char *submodule, each_ref_fn fn, void *c
{
return for_each_ref_in_submodule(submodule, "refs/remotes/", fn, cb_data);
}
+
+int head_ref_namespaced(each_ref_fn fn, void *cb_data)
+{
+ struct strbuf buf = STRBUF_INIT;
+ int ret = 0;
+ struct object_id oid;
+ int flag;
+
+ strbuf_addf(&buf, "%sHEAD", get_git_namespace());
+ if (!read_ref_full(buf.buf, RESOLVE_REF_READING, oid.hash, &flag))
+ ret = fn(buf.buf, &oid, flag, cb_data);
+ strbuf_release(&buf);
+
+ return ret;
+}
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v4 18/26] refs: move transaction functions into common code
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
` (16 preceding siblings ...)
2015-10-15 19:46 ` [PATCH v4 17/26] refs.c: move head_ref_namespaced " David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-15 19:46 ` [PATCH v4 19/26] refs.c: move refname_is_safe to the " David Turner
` (7 subsequent siblings)
25 siblings, 0 replies; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: David Turner, Junio C Hamano
The common ref code will build up a ref transaction. Backends will
then commit it. So the transaction creation and update functions should
be in the common code. We also need to move the ref structs into
the common code so that alternate backends can access them.
Later, we will modify struct ref_update to support alternate backends.
Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs-be-files.c | 198 --------------------------------------------------------
refs.c | 108 +++++++++++++++++++++++++++++++
refs.h | 91 +++++++++++++++++++++++++-
3 files changed, 198 insertions(+), 199 deletions(-)
diff --git a/refs-be-files.c b/refs-be-files.c
index ffc3813..73eb1e2 100644
--- a/refs-be-files.c
+++ b/refs-be-files.c
@@ -13,41 +13,6 @@ struct ref_lock {
struct object_id old_oid;
};
-/*
- * Flag passed to lock_ref_sha1_basic() telling it to tolerate broken
- * refs (i.e., because the reference is about to be deleted anyway).
- */
-#define REF_DELETING 0x02
-
-/*
- * Used as a flag in ref_update::flags when a loose ref is being
- * pruned.
- */
-#define REF_ISPRUNING 0x04
-
-/*
- * Used as a flag in ref_update::flags when the reference should be
- * updated to new_sha1.
- */
-#define REF_HAVE_NEW 0x08
-
-/*
- * Used as a flag in ref_update::flags when old_sha1 should be
- * checked.
- */
-#define REF_HAVE_OLD 0x10
-
-/*
- * Used as a flag in ref_update::flags when the lockfile needs to be
- * committed.
- */
-#define REF_NEEDS_COMMIT 0x20
-
-/*
- * 0x40 is REF_FORCE_CREATE_REFLOG, so skip it if you're adding a
- * value to ref_update::flags
- */
-
struct ref_entry;
/*
@@ -3289,169 +3254,6 @@ int for_each_reflog(each_ref_fn fn, void *cb_data)
return retval;
}
-/**
- * Information needed for a single ref update. Set new_sha1 to the new
- * value or to null_sha1 to delete the ref. To check the old value
- * while the ref is locked, set (flags & REF_HAVE_OLD) and set
- * old_sha1 to the old value, or to null_sha1 to ensure the ref does
- * not exist before update.
- */
-struct ref_update {
- /*
- * If (flags & REF_HAVE_NEW), set the reference to this value:
- */
- unsigned char new_sha1[20];
- /*
- * If (flags & REF_HAVE_OLD), check that the reference
- * previously had this value:
- */
- unsigned char old_sha1[20];
- /*
- * One or more of REF_HAVE_NEW, REF_HAVE_OLD, REF_NODEREF,
- * REF_DELETING, and REF_ISPRUNING:
- */
- unsigned int flags;
- struct ref_lock *lock;
- int type;
- char *msg;
- const char refname[FLEX_ARRAY];
-};
-
-/*
- * Transaction states.
- * OPEN: The transaction is in a valid state and can accept new updates.
- * An OPEN transaction can be committed.
- * CLOSED: A closed transaction is no longer active and no other operations
- * than free can be used on it in this state.
- * A transaction can either become closed by successfully committing
- * an active transaction or if there is a failure while building
- * the transaction thus rendering it failed/inactive.
- */
-enum ref_transaction_state {
- REF_TRANSACTION_OPEN = 0,
- REF_TRANSACTION_CLOSED = 1
-};
-
-/*
- * Data structure for holding a reference transaction, which can
- * consist of checks and updates to multiple references, carried out
- * as atomically as possible. This structure is opaque to callers.
- */
-struct ref_transaction {
- struct ref_update **updates;
- size_t alloc;
- size_t nr;
- enum ref_transaction_state state;
-};
-
-struct ref_transaction *ref_transaction_begin(struct strbuf *err)
-{
- assert(err);
-
- return xcalloc(1, sizeof(struct ref_transaction));
-}
-
-void ref_transaction_free(struct ref_transaction *transaction)
-{
- int i;
-
- if (!transaction)
- return;
-
- for (i = 0; i < transaction->nr; i++) {
- free(transaction->updates[i]->msg);
- free(transaction->updates[i]);
- }
- free(transaction->updates);
- free(transaction);
-}
-
-static struct ref_update *add_update(struct ref_transaction *transaction,
- const char *refname)
-{
- size_t len = strlen(refname) + 1;
- struct ref_update *update = xcalloc(1, sizeof(*update) + len);
-
- memcpy((char *)update->refname, refname, len); /* includes NUL */
- ALLOC_GROW(transaction->updates, transaction->nr + 1, transaction->alloc);
- transaction->updates[transaction->nr++] = update;
- return update;
-}
-
-int ref_transaction_update(struct ref_transaction *transaction,
- const char *refname,
- const unsigned char *new_sha1,
- const unsigned char *old_sha1,
- unsigned int flags, const char *msg,
- struct strbuf *err)
-{
- struct ref_update *update;
-
- assert(err);
-
- if (transaction->state != REF_TRANSACTION_OPEN)
- die("BUG: update called for transaction that is not open");
-
- if (new_sha1 && !is_null_sha1(new_sha1) &&
- check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
- strbuf_addf(err, "refusing to update ref with bad name %s",
- refname);
- return -1;
- }
-
- update = add_update(transaction, refname);
- if (new_sha1) {
- hashcpy(update->new_sha1, new_sha1);
- flags |= REF_HAVE_NEW;
- }
- if (old_sha1) {
- hashcpy(update->old_sha1, old_sha1);
- flags |= REF_HAVE_OLD;
- }
- update->flags = flags;
- if (msg)
- update->msg = xstrdup(msg);
- return 0;
-}
-
-int ref_transaction_create(struct ref_transaction *transaction,
- const char *refname,
- const unsigned char *new_sha1,
- unsigned int flags, const char *msg,
- struct strbuf *err)
-{
- if (!new_sha1 || is_null_sha1(new_sha1))
- die("BUG: create called without valid new_sha1");
- return ref_transaction_update(transaction, refname, new_sha1,
- null_sha1, flags, msg, err);
-}
-
-int ref_transaction_delete(struct ref_transaction *transaction,
- const char *refname,
- const unsigned char *old_sha1,
- unsigned int flags, const char *msg,
- struct strbuf *err)
-{
- if (old_sha1 && is_null_sha1(old_sha1))
- die("BUG: delete called with old_sha1 set to zeros");
- return ref_transaction_update(transaction, refname,
- null_sha1, old_sha1,
- flags, msg, err);
-}
-
-int ref_transaction_verify(struct ref_transaction *transaction,
- const char *refname,
- const unsigned char *old_sha1,
- unsigned int flags,
- struct strbuf *err)
-{
- if (!old_sha1)
- die("BUG: verify called with old_sha1 set to NULL");
- return ref_transaction_update(transaction, refname,
- NULL, old_sha1,
- flags, NULL, err);
-}
-
static int ref_update_reject_duplicates(struct string_list *refnames,
struct strbuf *err)
{
diff --git a/refs.c b/refs.c
index ae518a2..be08787 100644
--- a/refs.c
+++ b/refs.c
@@ -842,3 +842,111 @@ int head_ref_namespaced(each_ref_fn fn, void *cb_data)
return ret;
}
+
+struct ref_transaction *ref_transaction_begin(struct strbuf *err)
+{
+ assert(err);
+
+ return xcalloc(1, sizeof(struct ref_transaction));
+}
+
+void ref_transaction_free(struct ref_transaction *transaction)
+{
+ int i;
+
+ if (!transaction)
+ return;
+
+ for (i = 0; i < transaction->nr; i++) {
+ free(transaction->updates[i]->msg);
+ free(transaction->updates[i]);
+ }
+ free(transaction->updates);
+ free(transaction);
+}
+
+static struct ref_update *add_update(struct ref_transaction *transaction,
+ const char *refname)
+{
+ size_t len = strlen(refname) + 1;
+ struct ref_update *update = xcalloc(1, sizeof(*update) + len);
+
+ memcpy((char *)update->refname, refname, len); /* includes NUL */
+ ALLOC_GROW(transaction->updates, transaction->nr + 1, transaction->alloc);
+ transaction->updates[transaction->nr++] = update;
+ return update;
+}
+
+int ref_transaction_update(struct ref_transaction *transaction,
+ const char *refname,
+ const unsigned char *new_sha1,
+ const unsigned char *old_sha1,
+ unsigned int flags, const char *msg,
+ struct strbuf *err)
+{
+ struct ref_update *update;
+
+ assert(err);
+
+ if (transaction->state != REF_TRANSACTION_OPEN)
+ die("BUG: update called for transaction that is not open");
+
+ if (new_sha1 && !is_null_sha1(new_sha1) &&
+ check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
+ strbuf_addf(err, "refusing to update ref with bad name %s",
+ refname);
+ return -1;
+ }
+
+ update = add_update(transaction, refname);
+ if (new_sha1) {
+ hashcpy(update->new_sha1, new_sha1);
+ flags |= REF_HAVE_NEW;
+ }
+ if (old_sha1) {
+ hashcpy(update->old_sha1, old_sha1);
+ flags |= REF_HAVE_OLD;
+ }
+ update->flags = flags;
+ if (msg)
+ update->msg = xstrdup(msg);
+ return 0;
+}
+
+int ref_transaction_create(struct ref_transaction *transaction,
+ const char *refname,
+ const unsigned char *new_sha1,
+ unsigned int flags, const char *msg,
+ struct strbuf *err)
+{
+ if (!new_sha1 || is_null_sha1(new_sha1))
+ die("BUG: create called without valid new_sha1");
+ return ref_transaction_update(transaction, refname, new_sha1,
+ null_sha1, flags, msg, err);
+}
+
+int ref_transaction_delete(struct ref_transaction *transaction,
+ const char *refname,
+ const unsigned char *old_sha1,
+ unsigned int flags, const char *msg,
+ struct strbuf *err)
+{
+ if (old_sha1 && is_null_sha1(old_sha1))
+ die("BUG: delete called with old_sha1 set to zeros");
+ return ref_transaction_update(transaction, refname,
+ null_sha1, old_sha1,
+ flags, msg, err);
+}
+
+int ref_transaction_verify(struct ref_transaction *transaction,
+ const char *refname,
+ const unsigned char *old_sha1,
+ unsigned int flags,
+ struct strbuf *err)
+{
+ if (!old_sha1)
+ die("BUG: verify called with old_sha1 set to NULL");
+ return ref_transaction_update(transaction, refname,
+ NULL, old_sha1,
+ flags, NULL, err);
+}
diff --git a/refs.h b/refs.h
index 8408bef..3d24c79 100644
--- a/refs.h
+++ b/refs.h
@@ -94,6 +94,84 @@ extern int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref);
extern int dwim_log(const char *str, int len, unsigned char *sha1, char **ref);
/*
+ * Transaction states.
+ * OPEN: The transaction is in a valid state and can accept new updates.
+ * An OPEN transaction can be committed.
+ * CLOSED: A closed transaction is no longer active and no other operations
+ * than free can be used on it in this state.
+ * A transaction can either become closed by successfully committing
+ * an active transaction or if there is a failure while building
+ * the transaction thus rendering it failed/inactive.
+ */
+enum ref_transaction_state {
+ REF_TRANSACTION_OPEN = 0,
+ REF_TRANSACTION_CLOSED = 1
+};
+
+/*
+ * Flag passed to lock_ref_sha1_basic() telling it to tolerate broken
+ * refs (i.e., because the reference is about to be deleted anyway).
+ */
+#define REF_DELETING 0x02
+
+/*
+ * Used as a flag in ref_update::flags when a loose ref is being
+ * pruned.
+ */
+#define REF_ISPRUNING 0x04
+
+/*
+ * Used as a flag in ref_update::flags when the reference should be
+ * updated to new_sha1.
+ */
+#define REF_HAVE_NEW 0x08
+
+/*
+ * Used as a flag in ref_update::flags when old_sha1 should be
+ * checked.
+ */
+#define REF_HAVE_OLD 0x10
+
+/*
+ * Used as a flag in ref_update::flags when the lockfile needs to be
+ * committed.
+ */
+#define REF_NEEDS_COMMIT 0x20
+
+/*
+ * 0x40 is REF_FORCE_CREATE_REFLOG, so skip it if you're adding a
+ * value to ref_update::flags
+ */
+
+/**
+ * Information needed for a single ref update. Set new_sha1 to the new
+ * value or to null_sha1 to delete the ref. To check the old value
+ * while the ref is locked, set (flags & REF_HAVE_OLD) and set
+ * old_sha1 to the old value, or to null_sha1 to ensure the ref does
+ * not exist before update.
+ */
+struct ref_update {
+ /*
+ * If (flags & REF_HAVE_NEW), set the reference to this value:
+ */
+ unsigned char new_sha1[20];
+ /*
+ * If (flags & REF_HAVE_OLD), check that the reference
+ * previously had this value:
+ */
+ unsigned char old_sha1[20];
+ /*
+ * One or more of REF_HAVE_NEW, REF_HAVE_OLD, REF_NODEREF,
+ * REF_DELETING, and REF_ISPRUNING:
+ */
+ unsigned int flags;
+ struct ref_lock *lock;
+ int type;
+ char *msg;
+ const char refname[FLEX_ARRAY];
+};
+
+/*
* A ref_transaction represents a collection of ref updates
* that should succeed or fail together.
*
@@ -125,7 +203,18 @@ extern int dwim_log(const char *str, int len, unsigned char *sha1, char **ref);
* The message is appended to err without first clearing err.
* err will not be '\n' terminated.
*/
-struct ref_transaction;
+
+/*
+ * Data structure for holding a reference transaction, which can
+ * consist of checks and updates to multiple references, carried out
+ * as atomically as possible. This structure is opaque to callers.
+ */
+struct ref_transaction {
+ struct ref_update **updates;
+ size_t alloc;
+ size_t nr;
+ enum ref_transaction_state state;
+};
/*
* Bit values set in the flags argument passed to each_ref_fn():
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v4 19/26] refs.c: move refname_is_safe to the common code
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
` (17 preceding siblings ...)
2015-10-15 19:46 ` [PATCH v4 18/26] refs: move transaction functions into " David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-15 19:46 ` [PATCH v4 20/26] refs.c: move copy_msg " David Turner
` (6 subsequent siblings)
25 siblings, 0 replies; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: David Turner, Ronnie Sahlberg, Junio C Hamano
This function does not contain any backend specific code so we move it
to the common code. This function might be used by other refs backends.
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs-be-files.c | 33 ---------------------------------
refs.c | 24 ++++++++++++++++++++++++
refs.h | 11 +++++++++++
3 files changed, 35 insertions(+), 33 deletions(-)
diff --git a/refs-be-files.c b/refs-be-files.c
index 73eb1e2..8d966f1 100644
--- a/refs-be-files.c
+++ b/refs-be-files.c
@@ -196,39 +196,6 @@ static struct ref_dir *get_ref_dir(struct ref_entry *entry)
return dir;
}
-/*
- * Check if a refname is safe.
- * For refs that start with "refs/" we consider it safe as long they do
- * not try to resolve to outside of refs/.
- *
- * For all other refs we only consider them safe iff they only contain
- * upper case characters and '_' (like "HEAD" AND "MERGE_HEAD", and not like
- * "config").
- */
-static int refname_is_safe(const char *refname)
-{
- if (starts_with(refname, "refs/")) {
- char *buf;
- int result;
-
- buf = xmalloc(strlen(refname) + 1);
- /*
- * Does the refname try to escape refs/?
- * For example: refs/foo/../bar is safe but refs/foo/../../bar
- * is not.
- */
- result = !normalize_path_copy(buf, refname + strlen("refs/"));
- free(buf);
- return result;
- }
- while (*refname) {
- if (!isupper(*refname) && *refname != '_')
- return 0;
- refname++;
- }
- return 1;
-}
-
static struct ref_entry *create_ref_entry(const char *refname,
const unsigned char *sha1, int flag,
int check_name)
diff --git a/refs.c b/refs.c
index be08787..3eb3a28 100644
--- a/refs.c
+++ b/refs.c
@@ -950,3 +950,27 @@ int ref_transaction_verify(struct ref_transaction *transaction,
NULL, old_sha1,
flags, NULL, err);
}
+
+int refname_is_safe(const char *refname)
+{
+ if (starts_with(refname, "refs/")) {
+ char *buf;
+ int result;
+
+ buf = xmalloc(strlen(refname) + 1);
+ /*
+ * Does the refname try to escape refs/?
+ * For example: refs/foo/../bar is safe but refs/foo/../../bar
+ * is not.
+ */
+ result = !normalize_path_copy(buf, refname + strlen("refs/"));
+ free(buf);
+ return result;
+ }
+ while (*refname) {
+ if (!isupper(*refname) && *refname != '_')
+ return 0;
+ refname++;
+ }
+ return 1;
+}
diff --git a/refs.h b/refs.h
index 3d24c79..be94e18 100644
--- a/refs.h
+++ b/refs.h
@@ -396,6 +396,17 @@ extern int for_each_reflog(each_ref_fn, void *);
*/
extern int check_refname_format(const char *refname, int flags);
+/*
+ * Check if a refname is safe.
+ * For refs that start with "refs/" we consider it safe as long they do
+ * not try to resolve to outside of refs/.
+ *
+ * For all other refs we only consider them safe iff they only contain
+ * upper case characters and '_' (like "HEAD" AND "MERGE_HEAD", and not like
+ * "config").
+ */
+extern int refname_is_safe(const char *refname);
+
extern const char *prettify_refname(const char *refname);
extern char *shorten_unambiguous_ref(const char *refname, int strict);
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v4 20/26] refs.c: move copy_msg to the common code
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
` (18 preceding siblings ...)
2015-10-15 19:46 ` [PATCH v4 19/26] refs.c: move refname_is_safe to the " David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-15 19:46 ` [PATCH v4 21/26] refs.c: move peel_object " David Turner
` (5 subsequent siblings)
25 siblings, 0 replies; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: David Turner, Junio C Hamano
Rename copy_msg to copy_reflog_msg and make it public.
Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs-be-files.c | 28 +---------------------------
refs.c | 21 +++++++++++++++++++++
refs.h | 7 +++++++
3 files changed, 29 insertions(+), 27 deletions(-)
diff --git a/refs-be-files.c b/refs-be-files.c
index 8d966f1..4b6bf29 100644
--- a/refs-be-files.c
+++ b/refs-be-files.c
@@ -2654,32 +2654,6 @@ static int commit_ref(struct ref_lock *lock)
return 0;
}
-/*
- * 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.
- */
-static int copy_msg(char *buf, const char *msg)
-{
- char *cp = buf;
- char c;
- int wasspace = 1;
-
- *cp++ = '\t';
- while ((c = *msg++)) {
- if (wasspace && isspace(c))
- continue;
- wasspace = isspace(c);
- if (wasspace)
- c = ' ';
- *cp++ = c;
- }
- while (buf < cp && isspace(cp[-1]))
- cp--;
- *cp++ = '\n';
- return cp - buf;
-}
-
static int should_autocreate_reflog(const char *refname)
{
if (!log_all_ref_updates)
@@ -2774,7 +2748,7 @@ static int log_ref_write_fd(int fd, const unsigned char *old_sha1,
sha1_to_hex(new_sha1),
committer);
if (msglen)
- len += copy_msg(logrec + len - 1, msg) - 1;
+ len += copy_reflog_msg(logrec + len - 1, msg) - 1;
written = len <= maxlen ? write_in_full(fd, logrec, len) : -1;
free(logrec);
diff --git a/refs.c b/refs.c
index 3eb3a28..16280d5 100644
--- a/refs.c
+++ b/refs.c
@@ -828,6 +828,27 @@ int for_each_remote_ref_submodule(const char *submodule, each_ref_fn fn, void *c
return for_each_ref_in_submodule(submodule, "refs/remotes/", fn, cb_data);
}
+int copy_reflog_msg(char *buf, const char *msg)
+{
+ char *cp = buf;
+ char c;
+ int wasspace = 1;
+
+ *cp++ = '\t';
+ while ((c = *msg++)) {
+ if (wasspace && isspace(c))
+ continue;
+ wasspace = isspace(c);
+ if (wasspace)
+ c = ' ';
+ *cp++ = c;
+ }
+ while (buf < cp && isspace(cp[-1]))
+ cp--;
+ *cp++ = '\n';
+ return cp - buf;
+}
+
int head_ref_namespaced(each_ref_fn fn, void *cb_data)
{
struct strbuf buf = STRBUF_INIT;
diff --git a/refs.h b/refs.h
index be94e18..fc0611d 100644
--- a/refs.h
+++ b/refs.h
@@ -576,6 +576,13 @@ enum ref_type {
enum ref_type ref_type(const char *refname);
+/*
+ * 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.
+ */
+int copy_reflog_msg(char *buf, const char *msg);
+
enum expire_reflog_flags {
EXPIRE_REFLOGS_DRY_RUN = 1 << 0,
EXPIRE_REFLOGS_UPDATE_REF = 1 << 1,
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v4 21/26] refs.c: move peel_object to the common code
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
` (19 preceding siblings ...)
2015-10-15 19:46 ` [PATCH v4 20/26] refs.c: move copy_msg " David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-15 19:46 ` [PATCH v4 22/26] refs.c: move should_autocreate_reflog to " David Turner
` (4 subsequent siblings)
25 siblings, 0 replies; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: David Turner, Junio C Hamano
This function does not contain any backend specific code so we
move it to the common code.
Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs-be-files.c | 53 -----------------------------------------------------
refs.c | 23 +++++++++++++++++++++++
refs.h | 34 ++++++++++++++++++++++++++++++++++
3 files changed, 57 insertions(+), 53 deletions(-)
diff --git a/refs-be-files.c b/refs-be-files.c
index 4b6bf29..ef600d8 100644
--- a/refs-be-files.c
+++ b/refs-be-files.c
@@ -1600,59 +1600,6 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
return ret;
}
-enum peel_status {
- /* object was peeled successfully: */
- PEEL_PEELED = 0,
-
- /*
- * object cannot be peeled because the named object (or an
- * object referred to by a tag in the peel chain), does not
- * exist.
- */
- PEEL_INVALID = -1,
-
- /* object cannot be peeled because it is not a tag: */
- PEEL_NON_TAG = -2,
-
- /* ref_entry contains no peeled value because it is a symref: */
- PEEL_IS_SYMREF = -3,
-
- /*
- * ref_entry cannot be peeled because it is broken (i.e., the
- * symbolic reference cannot even be resolved to an object
- * name):
- */
- PEEL_BROKEN = -4
-};
-
-/*
- * Peel the named object; i.e., if the object is a tag, resolve the
- * tag recursively until a non-tag is found. If successful, store the
- * result to sha1 and return PEEL_PEELED. If the object is not a tag
- * or is not valid, return PEEL_NON_TAG or PEEL_INVALID, respectively,
- * and leave sha1 unchanged.
- */
-static enum peel_status peel_object(const unsigned char *name, unsigned char *sha1)
-{
- struct object *o = lookup_unknown_object(name);
-
- if (o->type == OBJ_NONE) {
- int type = sha1_object_info(name, NULL);
- if (type < 0 || !object_as_type(o, type, 0))
- return PEEL_INVALID;
- }
-
- if (o->type != OBJ_TAG)
- return PEEL_NON_TAG;
-
- o = deref_tag_noverify(o);
- if (!o)
- return PEEL_INVALID;
-
- hashcpy(sha1, o->sha1);
- return PEEL_PEELED;
-}
-
/*
* Peel the entry (if possible) and return its new peel_status. If
* repeel is true, re-peel the entry even if there is an old peeled
diff --git a/refs.c b/refs.c
index 16280d5..e7f6c77 100644
--- a/refs.c
+++ b/refs.c
@@ -4,6 +4,8 @@
#include "cache.h"
#include "refs.h"
#include "lockfile.h"
+#include "object.h"
+#include "tag.h"
static int is_per_worktree_ref(const char *refname)
{
@@ -995,3 +997,24 @@ int refname_is_safe(const char *refname)
}
return 1;
}
+
+enum peel_status peel_object(const unsigned char *name, unsigned char *sha1)
+{
+ struct object *o = lookup_unknown_object(name);
+
+ if (o->type == OBJ_NONE) {
+ int type = sha1_object_info(name, NULL);
+ if (type < 0 || !object_as_type(o, type, 0))
+ return PEEL_INVALID;
+ }
+
+ if (o->type != OBJ_TAG)
+ return PEEL_NON_TAG;
+
+ o = deref_tag_noverify(o);
+ if (!o)
+ return PEEL_INVALID;
+
+ hashcpy(sha1, o->sha1);
+ return PEEL_PEELED;
+}
diff --git a/refs.h b/refs.h
index fc0611d..3fb480b 100644
--- a/refs.h
+++ b/refs.h
@@ -76,6 +76,40 @@ extern int is_branch(const char *refname);
*/
extern int peel_ref(const char *refname, unsigned char *sha1);
+enum peel_status {
+ /* object was peeled successfully: */
+ PEEL_PEELED = 0,
+
+ /*
+ * object cannot be peeled because the named object (or an
+ * object referred to by a tag in the peel chain), does not
+ * exist.
+ */
+ PEEL_INVALID = -1,
+
+ /* object cannot be peeled because it is not a tag: */
+ PEEL_NON_TAG = -2,
+
+ /* ref_entry contains no peeled value because it is a symref: */
+ PEEL_IS_SYMREF = -3,
+
+ /*
+ * ref_entry cannot be peeled because it is broken (i.e., the
+ * symbolic reference cannot even be resolved to an object
+ * name):
+ */
+ PEEL_BROKEN = -4
+};
+
+/*
+ * Peel the named object; i.e., if the object is a tag, resolve the
+ * tag recursively until a non-tag is found. If successful, store the
+ * result to sha1 and return PEEL_PEELED. If the object is not a tag
+ * or is not valid, return PEEL_NON_TAG or PEEL_INVALID, respectively,
+ * and leave sha1 unchanged.
+ */
+enum peel_status peel_object(const unsigned char *name, unsigned char *sha1);
+
/**
* Resolve refname in the nested "gitlink" repository that is located
* at path. If the resolution is successful, return 0 and set sha1 to
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v4 22/26] refs.c: move should_autocreate_reflog to common code
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
` (20 preceding siblings ...)
2015-10-15 19:46 ` [PATCH v4 21/26] refs.c: move peel_object " David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-15 19:46 ` [PATCH v4 23/26] initdb: move safe_create_dir into " David Turner
` (3 subsequent siblings)
25 siblings, 0 replies; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: David Turner, Junio C Hamano
Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs-be-files.c | 10 ----------
refs.c | 10 ++++++++++
refs.h | 2 ++
3 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/refs-be-files.c b/refs-be-files.c
index ef600d8..7c39afa 100644
--- a/refs-be-files.c
+++ b/refs-be-files.c
@@ -2601,16 +2601,6 @@ static int commit_ref(struct ref_lock *lock)
return 0;
}
-static int should_autocreate_reflog(const char *refname)
-{
- if (!log_all_ref_updates)
- return 0;
- return starts_with(refname, "refs/heads/") ||
- starts_with(refname, "refs/remotes/") ||
- starts_with(refname, "refs/notes/") ||
- !strcmp(refname, "HEAD");
-}
-
int verify_refname_available(const char *newname, struct string_list *extra,
struct string_list *skip, struct strbuf *err)
{
diff --git a/refs.c b/refs.c
index e7f6c77..efc1c47 100644
--- a/refs.c
+++ b/refs.c
@@ -626,6 +626,16 @@ char *resolve_refdup(const char *refname, int resolve_flags,
sha1, flags));
}
+int should_autocreate_reflog(const char *refname)
+{
+ if (!log_all_ref_updates)
+ return 0;
+ return starts_with(refname, "refs/heads/") ||
+ starts_with(refname, "refs/remotes/") ||
+ starts_with(refname, "refs/notes/") ||
+ !strcmp(refname, "HEAD");
+}
+
/*
* How to handle various characters in refnames:
* 0: An acceptable character for refs
diff --git a/refs.h b/refs.h
index 3fb480b..3fce9c9 100644
--- a/refs.h
+++ b/refs.h
@@ -58,6 +58,8 @@ extern const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
extern char *resolve_refdup(const char *refname, int resolve_flags,
unsigned char *sha1, int *flags);
+extern int should_autocreate_reflog(const char *refname);
+
extern int read_ref_full(const char *refname, int resolve_flags,
unsigned char *sha1, int *flags);
extern int read_ref(const char *refname, unsigned char *sha1);
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v4 23/26] initdb: move safe_create_dir into common code
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
` (21 preceding siblings ...)
2015-10-15 19:46 ` [PATCH v4 22/26] refs.c: move should_autocreate_reflog to " David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-21 19:38 ` Junio C Hamano
2015-10-15 19:46 ` [PATCH v4 24/26] refs: make files_log_ref_write functions public David Turner
` (2 subsequent siblings)
25 siblings, 1 reply; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: David Turner, Junio C Hamano
In a moment, we'll create initdb functions for ref backends, and code
from initdb that calls this function needs to move into the files
backend. So this function needs to be public.
Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
builtin/init-db.c | 12 ------------
cache.h | 5 +++++
path.c | 12 ++++++++++++
3 files changed, 17 insertions(+), 12 deletions(-)
diff --git a/builtin/init-db.c b/builtin/init-db.c
index f59f407..07229d6 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -24,18 +24,6 @@ static int init_shared_repository = -1;
static const char *init_db_template_dir;
static const char *git_link;
-static void safe_create_dir(const char *dir, int share)
-{
- if (mkdir(dir, 0777) < 0) {
- if (errno != EEXIST) {
- perror(dir);
- exit(1);
- }
- }
- else if (share && adjust_shared_perm(dir))
- die(_("Could not make %s writable by group"), dir);
-}
-
static void copy_templates_1(struct strbuf *path, struct strbuf *template,
DIR *dir)
{
diff --git a/cache.h b/cache.h
index 9a905a8..1d8a051 100644
--- a/cache.h
+++ b/cache.h
@@ -1737,4 +1737,9 @@ void stat_validity_update(struct stat_validity *sv, int fd);
int versioncmp(const char *s1, const char *s2);
void sleep_millisec(int millisec);
+/*
+ * Create a directory and (if share is nonzero) adjust its permissions
+ * according to the shared_repository setting.
+ */
+void safe_create_dir(const char *dir, int share);
#endif /* CACHE_H */
diff --git a/path.c b/path.c
index 212695a..9e0283c 100644
--- a/path.c
+++ b/path.c
@@ -723,6 +723,18 @@ int adjust_shared_perm(const char *path)
return 0;
}
+void safe_create_dir(const char *dir, int share)
+{
+ if (mkdir(dir, 0777) < 0) {
+ if (errno != EEXIST) {
+ perror(dir);
+ exit(1);
+ }
+ }
+ else if (share && adjust_shared_perm(dir))
+ die(_("Could not make %s writable by group"), dir);
+}
+
static int have_same_root(const char *path1, const char *path2)
{
int is_abs1, is_abs2;
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v4 24/26] refs: make files_log_ref_write functions public
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
` (22 preceding siblings ...)
2015-10-15 19:46 ` [PATCH v4 23/26] initdb: move safe_create_dir into " David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-15 19:46 ` [PATCH v4 25/26] refs: break out ref conflict checks David Turner
2015-10-15 19:46 ` [PATCH v4 26/26] introduce "extensions" form of core.repositoryformatversion David Turner
25 siblings, 0 replies; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: David Turner, Junio C Hamano
Because HEAD and stash are per-worktree, refs.c needs to go through
the files backend to write these refs.
In this patch, we make one files backend internal functions
public. Later, we will use this to handle reflog updates for
per-worktree symbolic refs (HEAD).
Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs-be-files.c | 8 ++++++++
refs.h | 5 +++++
2 files changed, 13 insertions(+)
diff --git a/refs-be-files.c b/refs-be-files.c
index 7c39afa..1bda3e4 100644
--- a/refs-be-files.c
+++ b/refs-be-files.c
@@ -2733,6 +2733,14 @@ static int log_ref_write(const char *refname, const unsigned char *old_sha1,
const unsigned char *new_sha1, const char *msg,
int flags, struct strbuf *err)
{
+ return files_log_ref_write(refname, old_sha1, new_sha1, msg, flags,
+ err);
+}
+
+int files_log_ref_write(const char *refname, const unsigned char *old_sha1,
+ const unsigned char *new_sha1, const char *msg,
+ int flags, struct strbuf *err)
+{
struct strbuf sb = STRBUF_INIT;
int ret = log_ref_write_1(refname, old_sha1, new_sha1, msg, &sb, flags,
err);
diff --git a/refs.h b/refs.h
index 3fce9c9..7aed0a2 100644
--- a/refs.h
+++ b/refs.h
@@ -619,6 +619,11 @@ enum ref_type ref_type(const char *refname);
*/
int copy_reflog_msg(char *buf, const char *msg);
+int files_log_ref_write(const char *refname, const unsigned char *old_sha1,
+ const unsigned char *new_sha1, const char *msg,
+ int flags, struct strbuf *err);
+
+
enum expire_reflog_flags {
EXPIRE_REFLOGS_DRY_RUN = 1 << 0,
EXPIRE_REFLOGS_UPDATE_REF = 1 << 1,
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v4 25/26] refs: break out ref conflict checks
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
` (23 preceding siblings ...)
2015-10-15 19:46 ` [PATCH v4 24/26] refs: make files_log_ref_write functions public David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-15 19:46 ` [PATCH v4 26/26] introduce "extensions" form of core.repositoryformatversion David Turner
25 siblings, 0 replies; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: David Turner, Junio C Hamano
Create new function verify_no_descendants, to hold one of the ref
conflict checks used in verify_refname_available. Multiple backends
will need this function, so it goes in the common code.
rename_ref_available also moves to the common code, because alternate
backends might need it and it has no files-backend-specific code.
Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs-be-files.c | 49 ++++++++-----------------------------------------
refs.c | 38 ++++++++++++++++++++++++++++++++++++++
refs.h | 15 +++++++++++++++
3 files changed, 61 insertions(+), 41 deletions(-)
diff --git a/refs-be-files.c b/refs-be-files.c
index 1bda3e4..1f17348 100644
--- a/refs-be-files.c
+++ b/refs-be-files.c
@@ -729,6 +729,7 @@ static int verify_refname_available_dir(const char *refname,
struct strbuf *err)
{
const char *slash;
+ const char *extra_refname;
int pos;
struct strbuf dirname = STRBUF_INIT;
int ret = -1;
@@ -834,33 +835,15 @@ static int verify_refname_available_dir(const char *refname,
}
}
- if (extras) {
- /*
- * Check for entries in extras that start with
- * "$refname/". We do that by looking for the place
- * where "$refname/" would be inserted in extras. If
- * there is an entry at that position that starts with
- * "$refname/" and is not in skip, then we have a
- * conflict.
- */
- for (pos = string_list_find_insert_index(extras, dirname.buf, 0);
- pos < extras->nr; pos++) {
- const char *extra_refname = extras->items[pos].string;
-
- if (!starts_with(extra_refname, dirname.buf))
- break;
-
- if (!skip || !string_list_has_string(skip, extra_refname)) {
- strbuf_addf(err, "cannot process '%s' and '%s' at the same time",
- refname, extra_refname);
- goto cleanup;
- }
- }
+ extra_refname = find_descendant_ref(dirname.buf, extras, skip);
+ if (extra_refname) {
+ strbuf_addf(err,
+ "cannot process '%s' and '%s' at the same time",
+ refname, extra_refname);
+ } else {
+ ret = 0;
}
- /* No conflicts were found */
- ret = 0;
-
cleanup:
strbuf_release(&dirname);
return ret;
@@ -2461,22 +2444,6 @@ out:
return ret;
}
-static int rename_ref_available(const char *oldname, const char *newname)
-{
- struct string_list skip = STRING_LIST_INIT_NODUP;
- struct strbuf err = STRBUF_INIT;
- int ret;
-
- string_list_insert(&skip, oldname);
- ret = !verify_refname_available(newname, NULL, &skip, &err);
- if (!ret)
- error("%s", err.buf);
-
- string_list_clear(&skip, 0);
- strbuf_release(&err);
- return ret;
-}
-
static int write_ref_to_lockfile(struct ref_lock *lock,
const unsigned char *sha1, struct strbuf *err);
static int commit_ref_update(struct ref_lock *lock,
diff --git a/refs.c b/refs.c
index efc1c47..72d96ed 100644
--- a/refs.c
+++ b/refs.c
@@ -1028,3 +1028,41 @@ enum peel_status peel_object(const unsigned char *name, unsigned char *sha1)
hashcpy(sha1, o->sha1);
return PEEL_PEELED;
}
+
+const char *find_descendant_ref(const char *dirname,
+ const struct string_list *extras,
+ const struct string_list *skip)
+{
+ int pos;
+ if (!extras)
+ return NULL;
+
+ /* Look for the place where dirname would be inserted in extras. */
+ for (pos = string_list_find_insert_index(extras, dirname, 0);
+ pos < extras->nr; pos++) {
+ const char *extra_refname = extras->items[pos].string;
+
+ if (!starts_with(extra_refname, dirname))
+ break;
+
+ if (!skip || !string_list_has_string(skip, extra_refname))
+ return extra_refname;
+ }
+ return NULL;
+}
+
+int rename_ref_available(const char *oldname, const char *newname)
+{
+ struct string_list skip = STRING_LIST_INIT_NODUP;
+ struct strbuf err = STRBUF_INIT;
+ int ret;
+
+ string_list_insert(&skip, oldname);
+ ret = !verify_refname_available(newname, NULL, &skip, &err);
+ if (!ret)
+ error("%s", err.buf);
+
+ string_list_clear(&skip, 0);
+ strbuf_release(&err);
+ return ret;
+}
diff --git a/refs.h b/refs.h
index 7aed0a2..69fa4df 100644
--- a/refs.h
+++ b/refs.h
@@ -362,6 +362,8 @@ int pack_refs(unsigned int flags);
int verify_refname_available(const char *newname, struct string_list *extra,
struct string_list *skip, struct strbuf *err);
+int rename_ref_available(const char *oldname, const char *newname);
+
extern int is_branch(const char *refname);
/*
@@ -623,6 +625,19 @@ int files_log_ref_write(const char *refname, const unsigned char *old_sha1,
const unsigned char *new_sha1, const char *msg,
int flags, struct strbuf *err);
+/*
+ * Check for entries in extras that are within the specified
+ * directory, where dirname is a reference directory name including
+ * the trailing slash (e.g., "refs/heads/master/"). Ignore any
+ * conflicting references that are found in skip. If there is a
+ * conflicting reference, return its name.
+ *
+ * extras and skip must be sorted lists of reference names. skip can
+ * be NULL; extras cannot.
+ */
+const char *find_descendant_ref(const char *dirname,
+ const struct string_list *extras,
+ const struct string_list *skip);
enum expire_reflog_flags {
EXPIRE_REFLOGS_DRY_RUN = 1 << 0,
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v4 26/26] introduce "extensions" form of core.repositoryformatversion
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
` (24 preceding siblings ...)
2015-10-15 19:46 ` [PATCH v4 25/26] refs: break out ref conflict checks David Turner
@ 2015-10-15 19:46 ` David Turner
2015-10-21 19:40 ` Junio C Hamano
25 siblings, 1 reply; 35+ messages in thread
From: David Turner @ 2015-10-15 19:46 UTC (permalink / raw)
To: git, mhagger; +Cc: Jeff King
From: Jeff King <peff@peff.net>
Normally we try to avoid bumps of the whole-repository
core.repositoryformatversion field. However, it is
unavoidable if we want to safely change certain aspects of
git in a backwards-incompatible way (e.g., modifying the set
of ref tips that we must traverse to generate a list of
unreachable, safe-to-prune objects).
If we were to bump the repository version for every such
change, then any implementation understanding version `X`
would also have to understand `X-1`, `X-2`, and so forth,
even though the incompatibilities may be in orthogonal parts
of the system, and there is otherwise no reason we cannot
implement one without the other (or more importantly, that
the user cannot choose to use one feature without the other,
weighing the tradeoff in compatibility only for that
particular feature).
This patch documents the existing repositoryformatversion
strategy and introduces a new format, "1", which lets a
repository specify that it must run with an arbitrary set of
extensions. This can be used, for example:
- to inform git that the objects should not be pruned based
only on the reachability of the ref tips (e.g, because it
has "clone --shared" children)
- that the refs are stored in a format besides the usual
"refs" and "packed-refs" directories
Because we bump to format "1", and because format "1"
requires that a running git knows about any extensions
mentioned, we know that older versions of the code will not
do something dangerous when confronted with these new
formats.
For example, if the user chooses to use database storage for
refs, they may set the "extensions.refbackend" config to
"db". Older versions of git will not understand format "1"
and bail. Versions of git which understand "1" but do not
know about "refbackend", or which know about "refbackend"
but not about the "db" backend, will refuse to run. This is
annoying, of course, but much better than the alternative of
claiming that there are no refs in the repository, or
writing to a location that other implementations will not
read.
Note that we are only defining the rules for format 1 here.
We do not ever write format 1 ourselves; it is a tool that
is meant to be used by users and future extensions to
provide safety with older implementations.
Signed-off-by: Jeff King <peff@peff.net>
---
Documentation/technical/repository-version.txt | 81 ++++++++++++++++++++++++++
cache.h | 6 ++
setup.c | 37 +++++++++++-
t/t1302-repo-version.sh | 38 ++++++++++++
4 files changed, 159 insertions(+), 3 deletions(-)
create mode 100644 Documentation/technical/repository-version.txt
diff --git a/Documentation/technical/repository-version.txt b/Documentation/technical/repository-version.txt
new file mode 100644
index 0000000..3d7106d
--- /dev/null
+++ b/Documentation/technical/repository-version.txt
@@ -0,0 +1,81 @@
+Git Repository Format Versions
+==============================
+
+Every git repository is marked with a numeric version in the
+`core.repositoryformatversion` key of its `config` file. This version
+specifies the rules for operating on the on-disk repository data. An
+implementation of git which does not understand a particular version
+advertised by an on-disk repository MUST NOT operate on that repository;
+doing so risks not only producing wrong results, but actually losing
+data.
+
+Because of this rule, version bumps should be kept to an absolute
+minimum. Instead, we generally prefer these strategies:
+
+ - bumping format version numbers of individual data files (e.g.,
+ index, packfiles, etc). This restricts the incompatibilities only to
+ those files.
+
+ - introducing new data that gracefully degrades when used by older
+ clients (e.g., pack bitmap files are ignored by older clients, which
+ simply do not take advantage of the optimization they provide).
+
+A whole-repository format version bump should only be part of a change
+that cannot be independently versioned. For instance, if one were to
+change the reachability rules for objects, or the rules for locking
+refs, that would require a bump of the repository format version.
+
+Note that this applies only to accessing the repository's disk contents
+directly. An older client which understands only format `0` may still
+connect via `git://` to a repository using format `1`, as long as the
+server process understands format `1`.
+
+The preferred strategy for rolling out a version bump (whether whole
+repository or for a single file) is to teach git to read the new format,
+and allow writing the new format with a config switch or command line
+option (for experimentation or for those who do not care about backwards
+compatibility with older gits). Then after a long period to allow the
+reading capability to become common, we may switch to writing the new
+format by default.
+
+The currently defined format versions are:
+
+Version `0`
+-----------
+
+This is the format defined by the initial version of git, including but
+not limited to the format of the repository directory, the repository
+configuration file, and the object and ref storage. Specifying the
+complete behavior of git is beyond the scope of this document.
+
+Version `1`
+-----------
+
+This format is identical to version `0`, with the following exceptions:
+
+ 1. When reading the `core.repositoryformatversion` variable, a git
+ implementation which supports version 1 MUST also read any
+ configuration keys found in the `extensions` section of the
+ configuration file.
+
+ 2. If a version-1 repository specifies any `extensions.*` keys that
+ the running git has not implemented, the operation MUST NOT
+ proceed. Similarly, if the value of any known key is not understood
+ by the implementation, the operation MUST NOT proceed.
+
+Note that if no extensions are specified in the config file, then
+`core.repositoryformatversion` SHOULD be set to `0` (setting it to `1`
+provides no benefit, and makes the repository incompatible with older
+implementations of git).
+
+This document will serve as the master list for extensions. Any
+implementation wishing to define a new extension should make a note of
+it here, in order to claim the name.
+
+The defined extensions are:
+
+`noop`
+~~~~~~
+
+This extension does not change git's behavior at all. It is useful only
+for testing format-1 compatibility.
diff --git a/cache.h b/cache.h
index 1d8a051..4b03cb3 100644
--- a/cache.h
+++ b/cache.h
@@ -696,7 +696,13 @@ extern char *notes_ref_name;
extern int grafts_replace_parents;
+/*
+ * GIT_REPO_VERSION is the version we write by default. The
+ * _READ variant is the highest number we know how to
+ * handle.
+ */
#define GIT_REPO_VERSION 0
+#define GIT_REPO_VERSION_READ 1
extern int repository_format_version;
extern int check_repository_format(void);
diff --git a/setup.c b/setup.c
index 2b64cbb..0c29469 100644
--- a/setup.c
+++ b/setup.c
@@ -5,6 +5,7 @@
static int inside_git_dir = -1;
static int inside_work_tree = -1;
static int work_tree_config_is_bogus;
+static struct string_list unknown_extensions = STRING_LIST_INIT_DUP;
/*
* The input parameter must contain an absolute path, and it must already be
@@ -349,10 +350,23 @@ void setup_work_tree(void)
static int check_repo_format(const char *var, const char *value, void *cb)
{
+ const char *ext;
+
if (strcmp(var, "core.repositoryformatversion") == 0)
repository_format_version = git_config_int(var, value);
else if (strcmp(var, "core.sharedrepository") == 0)
shared_repository = git_config_perm(var, value);
+ else if (skip_prefix(var, "extensions.", &ext)) {
+ /*
+ * record any known extensions here; otherwise,
+ * we fall through to recording it as unknown, and
+ * check_repository_format will complain
+ */
+ if (!strcmp(ext, "noop"))
+ ;
+ else
+ string_list_append(&unknown_extensions, ext);
+ }
return 0;
}
@@ -363,6 +377,8 @@ static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
config_fn_t fn;
int ret = 0;
+ string_list_clear(&unknown_extensions, 0);
+
if (get_common_dir(&sb, gitdir))
fn = check_repo_format;
else
@@ -380,16 +396,31 @@ static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
* is a good one.
*/
git_config_early(fn, NULL, repo_config);
- if (GIT_REPO_VERSION < repository_format_version) {
+ if (GIT_REPO_VERSION_READ < repository_format_version) {
if (!nongit_ok)
die ("Expected git repo version <= %d, found %d",
- GIT_REPO_VERSION, repository_format_version);
+ GIT_REPO_VERSION_READ, repository_format_version);
warning("Expected git repo version <= %d, found %d",
- GIT_REPO_VERSION, repository_format_version);
+ GIT_REPO_VERSION_READ, repository_format_version);
warning("Please upgrade Git");
*nongit_ok = -1;
ret = -1;
}
+
+ if (repository_format_version >= 1 && unknown_extensions.nr) {
+ int i;
+
+ if (!nongit_ok)
+ die("unknown repository extension: %s",
+ unknown_extensions.items[0].string);
+
+ for (i = 0; i < unknown_extensions.nr; i++)
+ warning("unknown repository extension: %s",
+ unknown_extensions.items[i].string);
+ *nongit_ok = -1;
+ ret = -1;
+ }
+
strbuf_release(&sb);
return ret;
}
diff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh
index 0d9388a..8dd6fd7 100755
--- a/t/t1302-repo-version.sh
+++ b/t/t1302-repo-version.sh
@@ -67,4 +67,42 @@ test_expect_success 'gitdir required mode' '
)
'
+check_allow () {
+ git rev-parse --git-dir >actual &&
+ echo .git >expect &&
+ test_cmp expect actual
+}
+
+check_abort () {
+ test_must_fail git rev-parse --git-dir
+}
+
+# avoid git-config, since it cannot be trusted to run
+# in a repository with a broken version
+mkconfig () {
+ echo '[core]' &&
+ echo "repositoryformatversion = $1" &&
+ shift &&
+
+ if test $# -gt 0; then
+ echo '[extensions]' &&
+ for i in "$@"; do
+ echo "$i"
+ done
+ fi
+}
+
+while read outcome version extensions; do
+ test_expect_success "$outcome version=$version $extensions" "
+ mkconfig $version $extensions >.git/config &&
+ check_${outcome}
+ "
+done <<\EOF
+allow 0
+allow 1
+allow 1 noop
+abort 1 no-such-extension
+allow 0 no-such-extension
+EOF
+
test_done
--
2.4.2.644.g97b850b-twtrsrc
^ permalink raw reply related [flat|nested] 35+ messages in thread
* Re: [PATCH v4 02/26] refs: make repack_without_refs and is_branch public
2015-10-15 19:46 ` [PATCH v4 02/26] refs: make repack_without_refs and is_branch public David Turner
@ 2015-10-16 6:34 ` Michael Haggerty
2015-10-19 23:16 ` David Turner
0 siblings, 1 reply; 35+ messages in thread
From: Michael Haggerty @ 2015-10-16 6:34 UTC (permalink / raw)
To: David Turner, git; +Cc: Ronnie Sahlberg, Junio C Hamano
On 10/15/2015 09:46 PM, David Turner wrote:
> is_branch was already non-static, but this patch declares it in the
> header.
The commit message no longer reflects the patch.
> Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
> Signed-off-by: David Turner <dturner@twopensource.com>
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
> ---
> refs.c | 5 +++--
> refs.h | 2 ++
> 2 files changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/refs.c b/refs.c
> index fe71ea0..84abc82 100644
> --- a/refs.c
> +++ b/refs.c
> @@ -2816,8 +2816,9 @@ int pack_refs(unsigned int flags)
>
> /*
> * Rewrite the packed-refs file, omitting any refs listed in
> - * 'refnames'. On error, leave packed-refs unchanged, write an error
> - * message to 'err', and return a nonzero value.
> + * 'refnames'. On error, packed-refs will be unchanged, the return
> + * value is nonzero, and a message about the error is written to the
> + * 'err' strbuf.
^^^ ?
It is preferable for docstrings to be written in imperative form, so in
my opinion this is a step backwards...
...literally. Your "new" version comes from an older version of Git; it
was changed in
79e4d8a9b8 repack_without_refs(): make function private (2015-06-22)
to the imperative form.
Assuming you are using `git-format-patch` to prepare your patches, it is
always a good idea to read over the prepared email files before sending
them to the ML, to check for bloopers like this.
> *
> * The refs in 'refnames' needn't be sorted. `err` must not be NULL.
> */
> diff --git a/refs.h b/refs.h
> index 7367a7f..8408bef 100644
> --- a/refs.h
> +++ b/refs.h
> @@ -237,6 +237,8 @@ int pack_refs(unsigned int flags);
> int verify_refname_available(const char *newname, struct string_list *extra,
> struct string_list *skip, struct strbuf *err);
>
> +extern int is_branch(const char *refname);
> +
> /*
> * Flags controlling ref_transaction_update(), ref_transaction_create(), etc.
> * REF_NODEREF: act on the ref directly, instead of dereferencing
>
Michael
--
Michael Haggerty
mhagger@alum.mit.edu
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v4 03/26] refs-be-files.c: rename refs to refs-be-files
2015-10-15 19:46 ` [PATCH v4 03/26] refs-be-files.c: rename refs to refs-be-files David Turner
@ 2015-10-16 6:36 ` Michael Haggerty
0 siblings, 0 replies; 35+ messages in thread
From: Michael Haggerty @ 2015-10-16 6:36 UTC (permalink / raw)
To: David Turner, git; +Cc: Ronnie Sahlberg, Junio C Hamano
On 10/15/2015 09:46 PM, David Turner wrote:
> From: Ronnie Sahlberg <sahlberg@google.com>
>
> Rename refs.c to refs-be-files.c to indicate that this file now
> holds the implementation for the files based refs backend.
> A smaller portion of the code in this file is backend agnostic and will
> be moved to a a new refs.c file that will hold all the common refs code
"a" is repeated above.
> that is shared across all backends.
>
> A second reason for first moving all the code to the new file and then
> move the backend agnostic code back to refs.c instead of the other way
> around is because the code that will eventually remain in this new
> refs-be-files.c file is so entangled that it would then be very
> difficult to break the split up into small independent patches/chunks.
> [...]
Michael
--
Michael Haggerty
mhagger@alum.mit.edu
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v4 02/26] refs: make repack_without_refs and is_branch public
2015-10-16 6:34 ` Michael Haggerty
@ 2015-10-19 23:16 ` David Turner
0 siblings, 0 replies; 35+ messages in thread
From: David Turner @ 2015-10-19 23:16 UTC (permalink / raw)
To: Michael Haggerty; +Cc: git, Junio C Hamano
On Fri, 2015-10-16 at 08:34 +0200, Michael Haggerty wrote:
> On 10/15/2015 09:46 PM, David Turner wrote:
> > is_branch was already non-static, but this patch declares it in the
> > header.
>
> The commit message no longer reflects the patch.
>
> > Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
> > Signed-off-by: David Turner <dturner@twopensource.com>
> > Signed-off-by: Junio C Hamano <gitster@pobox.com>
> > ---
> > refs.c | 5 +++--
> > refs.h | 2 ++
> > 2 files changed, 5 insertions(+), 2 deletions(-)
> >
> > diff --git a/refs.c b/refs.c
> > index fe71ea0..84abc82 100644
> > --- a/refs.c
> > +++ b/refs.c
> > @@ -2816,8 +2816,9 @@ int pack_refs(unsigned int flags)
> >
> > /*
> > * Rewrite the packed-refs file, omitting any refs listed in
> > - * 'refnames'. On error, leave packed-refs unchanged, write an error
> > - * message to 'err', and return a nonzero value.
> > + * 'refnames'. On error, packed-refs will be unchanged, the return
> > + * value is nonzero, and a message about the error is written to the
> > + * 'err' strbuf.
>
> ^^^ ?
>
> It is preferable for docstrings to be written in imperative form, so in
> my opinion this is a step backwards...
>
> ...literally. Your "new" version comes from an older version of Git; it
> was changed in
>
> 79e4d8a9b8 repack_without_refs(): make function private (2015-06-22)
>
> to the imperative form.
>
> Assuming you are using `git-format-patch` to prepare your patches, it is
> always a good idea to read over the prepared email files before sending
> them to the ML, to check for bloopers like this.
Sorry about that one. It's hard to keep track of what all of these
patches do -- especially the ones that were rebases of Ronnie's. I've
fixed that and 03/26 as well.
Do you have comments on any of the rest before I re-roll?
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v4 05/26] refs.c: move update_ref to refs.c
2015-10-15 19:46 ` [PATCH v4 05/26] refs.c: move update_ref to refs.c David Turner
@ 2015-10-21 19:03 ` David Turner
0 siblings, 0 replies; 35+ messages in thread
From: David Turner @ 2015-10-21 19:03 UTC (permalink / raw)
To: git; +Cc: mhagger, Ronnie Sahlberg, Junio C Hamano
On Thu, 2015-10-15 at 15:46 -0400, David Turner wrote:
> From: Ronnie Sahlberg <sahlberg@google.com>
>
> Move update_ref() to the refs.c file since this function does not
> contain any backend specific code. Move the ref classifier functions
and write_pseudoref (will fix on reroll).
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v4 06/26] refs.c: move delete_pseudoref and delete_ref to the common code
2015-10-15 19:46 ` [PATCH v4 06/26] refs.c: move delete_pseudoref and delete_ref to the common code David Turner
@ 2015-10-21 19:04 ` David Turner
0 siblings, 0 replies; 35+ messages in thread
From: David Turner @ 2015-10-21 19:04 UTC (permalink / raw)
To: git; +Cc: mhagger, Ronnie Sahlberg, Junio C Hamano
On Thu, 2015-10-15 at 15:46 -0400, David Turner wrote:
> --- a/refs.c
> +++ b/refs.c
> @@ -117,3 +117,60 @@ int update_ref(const char *msg, const char *refname,
> ref_transaction_free(t);
> return 0;
> }
> +
> +
> +static int delete_pseudoref(const char *pseudoref, const unsigned char *old_sha1)
extra newline (will fix on reroll)
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v4 23/26] initdb: move safe_create_dir into common code
2015-10-15 19:46 ` [PATCH v4 23/26] initdb: move safe_create_dir into " David Turner
@ 2015-10-21 19:38 ` Junio C Hamano
2015-10-21 19:47 ` David Turner
0 siblings, 1 reply; 35+ messages in thread
From: Junio C Hamano @ 2015-10-21 19:38 UTC (permalink / raw)
To: David Turner; +Cc: git, mhagger
David Turner <dturner@twopensource.com> writes:
> In a moment, we'll create initdb functions for ref backends, and code
> from initdb that calls this function needs to move into the files
> backend. So this function needs to be public.
OK, but unlike the static function, being in public interface part
can invite mistakes of using this for things outside $GIT_DIR [*1*].
Let's have "Never use this for working tree directories" somewhere
in its docstring.
Other than that, this one, 24/26 and 25/26 looked fine to me.
Thanks.
[Footnote]
*1* Anything created by this function and everything underneath are
repository metadata and this function must not be used to do with
anything with the working tree, as it is clear with the use of
adjust_shared_perm().
> diff --git a/cache.h b/cache.h
> index 9a905a8..1d8a051 100644
> --- a/cache.h
> +++ b/cache.h
> @@ -1737,4 +1737,9 @@ void stat_validity_update(struct stat_validity *sv, int fd);
> int versioncmp(const char *s1, const char *s2);
> void sleep_millisec(int millisec);
>
> +/*
> + * Create a directory and (if share is nonzero) adjust its permissions
> + * according to the shared_repository setting.
> + */
> +void safe_create_dir(const char *dir, int share);
> #endif /* CACHE_H */
> diff --git a/path.c b/path.c
> index 212695a..9e0283c 100644
> --- a/path.c
> +++ b/path.c
> @@ -723,6 +723,18 @@ int adjust_shared_perm(const char *path)
> return 0;
> }
>
> +void safe_create_dir(const char *dir, int share)
> +{
> + if (mkdir(dir, 0777) < 0) {
> + if (errno != EEXIST) {
> + perror(dir);
> + exit(1);
> + }
> + }
> + else if (share && adjust_shared_perm(dir))
> + die(_("Could not make %s writable by group"), dir);
> +}
> +
> static int have_same_root(const char *path1, const char *path2)
> {
> int is_abs1, is_abs2;
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v4 26/26] introduce "extensions" form of core.repositoryformatversion
2015-10-15 19:46 ` [PATCH v4 26/26] introduce "extensions" form of core.repositoryformatversion David Turner
@ 2015-10-21 19:40 ` Junio C Hamano
0 siblings, 0 replies; 35+ messages in thread
From: Junio C Hamano @ 2015-10-21 19:40 UTC (permalink / raw)
To: David Turner; +Cc: git, mhagger, Jeff King
David Turner <dturner@twopensource.com> writes:
> From: Jeff King <peff@peff.net>
I just made sure this is bit-for-bit identical with the first of the
two patches I received from Peff and I locally have kept.
Re-reading the two patches again, I do not see a reason why we should
reject them. I'll queue this and the other "precious object" one
separately.
Thanks.
>
> Normally we try to avoid bumps of the whole-repository
> core.repositoryformatversion field. However, it is
> unavoidable if we want to safely change certain aspects of
> git in a backwards-incompatible way (e.g., modifying the set
> of ref tips that we must traverse to generate a list of
> unreachable, safe-to-prune objects).
>
> If we were to bump the repository version for every such
> change, then any implementation understanding version `X`
> would also have to understand `X-1`, `X-2`, and so forth,
> even though the incompatibilities may be in orthogonal parts
> of the system, and there is otherwise no reason we cannot
> implement one without the other (or more importantly, that
> the user cannot choose to use one feature without the other,
> weighing the tradeoff in compatibility only for that
> particular feature).
>
> This patch documents the existing repositoryformatversion
> strategy and introduces a new format, "1", which lets a
> repository specify that it must run with an arbitrary set of
> extensions. This can be used, for example:
>
> - to inform git that the objects should not be pruned based
> only on the reachability of the ref tips (e.g, because it
> has "clone --shared" children)
>
> - that the refs are stored in a format besides the usual
> "refs" and "packed-refs" directories
>
> Because we bump to format "1", and because format "1"
> requires that a running git knows about any extensions
> mentioned, we know that older versions of the code will not
> do something dangerous when confronted with these new
> formats.
>
> For example, if the user chooses to use database storage for
> refs, they may set the "extensions.refbackend" config to
> "db". Older versions of git will not understand format "1"
> and bail. Versions of git which understand "1" but do not
> know about "refbackend", or which know about "refbackend"
> but not about the "db" backend, will refuse to run. This is
> annoying, of course, but much better than the alternative of
> claiming that there are no refs in the repository, or
> writing to a location that other implementations will not
> read.
>
> Note that we are only defining the rules for format 1 here.
> We do not ever write format 1 ourselves; it is a tool that
> is meant to be used by users and future extensions to
> provide safety with older implementations.
>
> Signed-off-by: Jeff King <peff@peff.net>
> ---
> Documentation/technical/repository-version.txt | 81 ++++++++++++++++++++++++++
> cache.h | 6 ++
> setup.c | 37 +++++++++++-
> t/t1302-repo-version.sh | 38 ++++++++++++
> 4 files changed, 159 insertions(+), 3 deletions(-)
> create mode 100644 Documentation/technical/repository-version.txt
>
> diff --git a/Documentation/technical/repository-version.txt b/Documentation/technical/repository-version.txt
> new file mode 100644
> index 0000000..3d7106d
> --- /dev/null
> +++ b/Documentation/technical/repository-version.txt
> @@ -0,0 +1,81 @@
> +Git Repository Format Versions
> +==============================
> +
> +Every git repository is marked with a numeric version in the
> +`core.repositoryformatversion` key of its `config` file. This version
> +specifies the rules for operating on the on-disk repository data. An
> +implementation of git which does not understand a particular version
> +advertised by an on-disk repository MUST NOT operate on that repository;
> +doing so risks not only producing wrong results, but actually losing
> +data.
> +
> +Because of this rule, version bumps should be kept to an absolute
> +minimum. Instead, we generally prefer these strategies:
> +
> + - bumping format version numbers of individual data files (e.g.,
> + index, packfiles, etc). This restricts the incompatibilities only to
> + those files.
> +
> + - introducing new data that gracefully degrades when used by older
> + clients (e.g., pack bitmap files are ignored by older clients, which
> + simply do not take advantage of the optimization they provide).
> +
> +A whole-repository format version bump should only be part of a change
> +that cannot be independently versioned. For instance, if one were to
> +change the reachability rules for objects, or the rules for locking
> +refs, that would require a bump of the repository format version.
> +
> +Note that this applies only to accessing the repository's disk contents
> +directly. An older client which understands only format `0` may still
> +connect via `git://` to a repository using format `1`, as long as the
> +server process understands format `1`.
> +
> +The preferred strategy for rolling out a version bump (whether whole
> +repository or for a single file) is to teach git to read the new format,
> +and allow writing the new format with a config switch or command line
> +option (for experimentation or for those who do not care about backwards
> +compatibility with older gits). Then after a long period to allow the
> +reading capability to become common, we may switch to writing the new
> +format by default.
> +
> +The currently defined format versions are:
> +
> +Version `0`
> +-----------
> +
> +This is the format defined by the initial version of git, including but
> +not limited to the format of the repository directory, the repository
> +configuration file, and the object and ref storage. Specifying the
> +complete behavior of git is beyond the scope of this document.
> +
> +Version `1`
> +-----------
> +
> +This format is identical to version `0`, with the following exceptions:
> +
> + 1. When reading the `core.repositoryformatversion` variable, a git
> + implementation which supports version 1 MUST also read any
> + configuration keys found in the `extensions` section of the
> + configuration file.
> +
> + 2. If a version-1 repository specifies any `extensions.*` keys that
> + the running git has not implemented, the operation MUST NOT
> + proceed. Similarly, if the value of any known key is not understood
> + by the implementation, the operation MUST NOT proceed.
> +
> +Note that if no extensions are specified in the config file, then
> +`core.repositoryformatversion` SHOULD be set to `0` (setting it to `1`
> +provides no benefit, and makes the repository incompatible with older
> +implementations of git).
> +
> +This document will serve as the master list for extensions. Any
> +implementation wishing to define a new extension should make a note of
> +it here, in order to claim the name.
> +
> +The defined extensions are:
> +
> +`noop`
> +~~~~~~
> +
> +This extension does not change git's behavior at all. It is useful only
> +for testing format-1 compatibility.
> diff --git a/cache.h b/cache.h
> index 1d8a051..4b03cb3 100644
> --- a/cache.h
> +++ b/cache.h
> @@ -696,7 +696,13 @@ extern char *notes_ref_name;
>
> extern int grafts_replace_parents;
>
> +/*
> + * GIT_REPO_VERSION is the version we write by default. The
> + * _READ variant is the highest number we know how to
> + * handle.
> + */
> #define GIT_REPO_VERSION 0
> +#define GIT_REPO_VERSION_READ 1
> extern int repository_format_version;
> extern int check_repository_format(void);
>
> diff --git a/setup.c b/setup.c
> index 2b64cbb..0c29469 100644
> --- a/setup.c
> +++ b/setup.c
> @@ -5,6 +5,7 @@
> static int inside_git_dir = -1;
> static int inside_work_tree = -1;
> static int work_tree_config_is_bogus;
> +static struct string_list unknown_extensions = STRING_LIST_INIT_DUP;
>
> /*
> * The input parameter must contain an absolute path, and it must already be
> @@ -349,10 +350,23 @@ void setup_work_tree(void)
>
> static int check_repo_format(const char *var, const char *value, void *cb)
> {
> + const char *ext;
> +
> if (strcmp(var, "core.repositoryformatversion") == 0)
> repository_format_version = git_config_int(var, value);
> else if (strcmp(var, "core.sharedrepository") == 0)
> shared_repository = git_config_perm(var, value);
> + else if (skip_prefix(var, "extensions.", &ext)) {
> + /*
> + * record any known extensions here; otherwise,
> + * we fall through to recording it as unknown, and
> + * check_repository_format will complain
> + */
> + if (!strcmp(ext, "noop"))
> + ;
> + else
> + string_list_append(&unknown_extensions, ext);
> + }
> return 0;
> }
>
> @@ -363,6 +377,8 @@ static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
> config_fn_t fn;
> int ret = 0;
>
> + string_list_clear(&unknown_extensions, 0);
> +
> if (get_common_dir(&sb, gitdir))
> fn = check_repo_format;
> else
> @@ -380,16 +396,31 @@ static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
> * is a good one.
> */
> git_config_early(fn, NULL, repo_config);
> - if (GIT_REPO_VERSION < repository_format_version) {
> + if (GIT_REPO_VERSION_READ < repository_format_version) {
> if (!nongit_ok)
> die ("Expected git repo version <= %d, found %d",
> - GIT_REPO_VERSION, repository_format_version);
> + GIT_REPO_VERSION_READ, repository_format_version);
> warning("Expected git repo version <= %d, found %d",
> - GIT_REPO_VERSION, repository_format_version);
> + GIT_REPO_VERSION_READ, repository_format_version);
> warning("Please upgrade Git");
> *nongit_ok = -1;
> ret = -1;
> }
> +
> + if (repository_format_version >= 1 && unknown_extensions.nr) {
> + int i;
> +
> + if (!nongit_ok)
> + die("unknown repository extension: %s",
> + unknown_extensions.items[0].string);
> +
> + for (i = 0; i < unknown_extensions.nr; i++)
> + warning("unknown repository extension: %s",
> + unknown_extensions.items[i].string);
> + *nongit_ok = -1;
> + ret = -1;
> + }
> +
> strbuf_release(&sb);
> return ret;
> }
> diff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh
> index 0d9388a..8dd6fd7 100755
> --- a/t/t1302-repo-version.sh
> +++ b/t/t1302-repo-version.sh
> @@ -67,4 +67,42 @@ test_expect_success 'gitdir required mode' '
> )
> '
>
> +check_allow () {
> + git rev-parse --git-dir >actual &&
> + echo .git >expect &&
> + test_cmp expect actual
> +}
> +
> +check_abort () {
> + test_must_fail git rev-parse --git-dir
> +}
> +
> +# avoid git-config, since it cannot be trusted to run
> +# in a repository with a broken version
> +mkconfig () {
> + echo '[core]' &&
> + echo "repositoryformatversion = $1" &&
> + shift &&
> +
> + if test $# -gt 0; then
> + echo '[extensions]' &&
> + for i in "$@"; do
> + echo "$i"
> + done
> + fi
> +}
> +
> +while read outcome version extensions; do
> + test_expect_success "$outcome version=$version $extensions" "
> + mkconfig $version $extensions >.git/config &&
> + check_${outcome}
> + "
> +done <<\EOF
> +allow 0
> +allow 1
> +allow 1 noop
> +abort 1 no-such-extension
> +allow 0 no-such-extension
> +EOF
> +
> test_done
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v4 23/26] initdb: move safe_create_dir into common code
2015-10-21 19:38 ` Junio C Hamano
@ 2015-10-21 19:47 ` David Turner
0 siblings, 0 replies; 35+ messages in thread
From: David Turner @ 2015-10-21 19:47 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, mhagger
On Wed, 2015-10-21 at 12:38 -0700, Junio C Hamano wrote:
> David Turner <dturner@twopensource.com> writes:
>
> > In a moment, we'll create initdb functions for ref backends, and code
> > from initdb that calls this function needs to move into the files
> > backend. So this function needs to be public.
>
> OK, but unlike the static function, being in public interface part
> can invite mistakes of using this for things outside $GIT_DIR [*1*].
> Let's have "Never use this for working tree directories" somewhere
> in its docstring.
Will fix in the re-roll, thanks.
^ permalink raw reply [flat|nested] 35+ messages in thread
end of thread, other threads:[~2015-10-21 19:48 UTC | newest]
Thread overview: 35+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-10-15 19:46 [PATCH v4 00/26] refs backend pre-vtable patches David Turner
2015-10-15 19:46 ` [PATCH v4 01/26] refs.c: create a public version of verify_refname_available David Turner
2015-10-15 19:46 ` [PATCH v4 02/26] refs: make repack_without_refs and is_branch public David Turner
2015-10-16 6:34 ` Michael Haggerty
2015-10-19 23:16 ` David Turner
2015-10-15 19:46 ` [PATCH v4 03/26] refs-be-files.c: rename refs to refs-be-files David Turner
2015-10-16 6:36 ` Michael Haggerty
2015-10-15 19:46 ` [PATCH v4 04/26] refs.c: add a new refs.c file to hold all common refs code David Turner
2015-10-15 19:46 ` [PATCH v4 05/26] refs.c: move update_ref to refs.c David Turner
2015-10-21 19:03 ` David Turner
2015-10-15 19:46 ` [PATCH v4 06/26] refs.c: move delete_pseudoref and delete_ref to the common code David Turner
2015-10-21 19:04 ` David Turner
2015-10-15 19:46 ` [PATCH v4 07/26] refs.c: move read_ref_at to the common refs file David Turner
2015-10-15 19:46 ` [PATCH v4 08/26] refs.c: move the hidden refs functions to the common code David Turner
2015-10-15 19:46 ` [PATCH v4 09/26] refs.c: move dwim and friend functions to the common refs code David Turner
2015-10-15 19:46 ` [PATCH v4 10/26] refs.c: move warn_if_dangling_symref* to the common code David Turner
2015-10-15 19:46 ` [PATCH v4 11/26] refs.c: move read_ref, read_ref_full and ref_exists " David Turner
2015-10-15 19:46 ` [PATCH v4 12/26] refs.c: move resolve_refdup to common David Turner
2015-10-15 19:46 ` [PATCH v4 13/26] refs.c: move check_refname_format to the common code David Turner
2015-10-15 19:46 ` [PATCH v4 14/26] refs.c: move is_branch " David Turner
2015-10-15 19:46 ` [PATCH v4 15/26] refs.c: move prettify_refname " David Turner
2015-10-15 19:46 ` [PATCH v4 16/26] refs.c: move ref iterators " David Turner
2015-10-15 19:46 ` [PATCH v4 17/26] refs.c: move head_ref_namespaced " David Turner
2015-10-15 19:46 ` [PATCH v4 18/26] refs: move transaction functions into " David Turner
2015-10-15 19:46 ` [PATCH v4 19/26] refs.c: move refname_is_safe to the " David Turner
2015-10-15 19:46 ` [PATCH v4 20/26] refs.c: move copy_msg " David Turner
2015-10-15 19:46 ` [PATCH v4 21/26] refs.c: move peel_object " David Turner
2015-10-15 19:46 ` [PATCH v4 22/26] refs.c: move should_autocreate_reflog to " David Turner
2015-10-15 19:46 ` [PATCH v4 23/26] initdb: move safe_create_dir into " David Turner
2015-10-21 19:38 ` Junio C Hamano
2015-10-21 19:47 ` David Turner
2015-10-15 19:46 ` [PATCH v4 24/26] refs: make files_log_ref_write functions public David Turner
2015-10-15 19:46 ` [PATCH v4 25/26] refs: break out ref conflict checks David Turner
2015-10-15 19:46 ` [PATCH v4 26/26] introduce "extensions" form of core.repositoryformatversion David Turner
2015-10-21 19:40 ` Junio C Hamano
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).