* [PATCH v5 17/24] refs: rename get_ref_store() to get_submodule_ref_store() and make it public
From: Nguyễn Thái Ngọc Duy @ 2017-02-22 14:04 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Michael Haggerty, Johannes Schindelin,
Ramsay Jones, Stefan Beller, novalis,
Nguyễn Thái Ngọc Duy
In-Reply-To: <20170222140450.30886-1-pclouds@gmail.com>
This function is intended to replace *_submodule() refs API. It provides
a ref store for a specific submodule, which can be operated on by a new
set of refs API.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
refs.c | 12 ++++++++----
refs.h | 11 +++++++++++
refs/refs-internal.h | 12 ------------
3 files changed, 19 insertions(+), 16 deletions(-)
diff --git a/refs.c b/refs.c
index 2dc97891a..7843d3085 100644
--- a/refs.c
+++ b/refs.c
@@ -1171,7 +1171,7 @@ int head_ref(each_ref_fn fn, void *cb_data)
static int do_for_each_ref(const char *submodule, const char *prefix,
each_ref_fn fn, int trim, int flags, void *cb_data)
{
- struct ref_store *refs = get_ref_store(submodule);
+ struct ref_store *refs = get_submodule_ref_store(submodule);
struct ref_iterator *iter;
if (!refs)
@@ -1344,10 +1344,10 @@ int resolve_gitlink_ref(const char *submodule, const char *refname,
/* We need to strip off one or more trailing slashes */
char *stripped = xmemdupz(submodule, len);
- refs = get_ref_store(stripped);
+ refs = get_submodule_ref_store(stripped);
free(stripped);
} else {
- refs = get_ref_store(submodule);
+ refs = get_submodule_ref_store(submodule);
}
if (!refs)
@@ -1468,13 +1468,17 @@ static void register_submodule_ref_store(struct ref_store *refs,
submodule);
}
-struct ref_store *get_ref_store(const char *submodule)
+struct ref_store *get_submodule_ref_store(const char *submodule)
{
struct strbuf submodule_sb = STRBUF_INIT;
struct ref_store *refs;
int ret;
if (!submodule || !*submodule) {
+ /*
+ * FIXME: This case is ideally not allowed. But that
+ * can't happen until we clean up all the callers.
+ */
return get_main_ref_store();
}
diff --git a/refs.h b/refs.h
index 29013cb7e..2efba6ba9 100644
--- a/refs.h
+++ b/refs.h
@@ -561,5 +561,16 @@ int reflog_expire(const char *refname, const unsigned char *sha1,
int ref_storage_backend_exists(const char *name);
struct ref_store *get_main_ref_store(void);
+/*
+ * Return the ref_store instance for the specified submodule. For the
+ * main repository, use submodule==NULL; such a call cannot fail. For
+ * a submodule, the submodule must exist and be a nonbare repository,
+ * otherwise return NULL. If the requested reference store has not yet
+ * been initialized, initialize it first.
+ *
+ * For backwards compatibility, submodule=="" is treated the same as
+ * submodule==NULL.
+ */
+struct ref_store *get_submodule_ref_store(const char *submodule);
#endif /* REFS_H */
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index 0cca280b5..f20dde39e 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -646,18 +646,6 @@ struct ref_store {
void base_ref_store_init(struct ref_store *refs,
const struct ref_storage_be *be);
-/*
- * Return the ref_store instance for the specified submodule. For the
- * main repository, use submodule==NULL; such a call cannot fail. For
- * a submodule, the submodule must exist and be a nonbare repository,
- * otherwise return NULL. If the requested reference store has not yet
- * been initialized, initialize it first.
- *
- * For backwards compatibility, submodule=="" is treated the same as
- * submodule==NULL.
- */
-struct ref_store *get_ref_store(const char *submodule);
-
const char *resolve_ref_recursively(struct ref_store *refs,
const char *refname,
int resolve_flags,
--
2.11.0.157.gd943d85
^ permalink raw reply related
* [PATCH v5 18/24] refs: add new ref-store api
From: Nguyễn Thái Ngọc Duy @ 2017-02-22 14:04 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Michael Haggerty, Johannes Schindelin,
Ramsay Jones, Stefan Beller, novalis,
Nguyễn Thái Ngọc Duy
In-Reply-To: <20170222140450.30886-1-pclouds@gmail.com>
This is not meant to cover all existing API. It adds enough to test ref
stores with the new test program test-ref-store, coming soon and to be
used by files-backend.c.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
refs.c | 235 +++++++++++++++++++++++++++++++++++++--------------
refs.h | 71 ++++++++++++++++
refs/files-backend.c | 13 +--
refs/refs-internal.h | 31 +------
4 files changed, 253 insertions(+), 97 deletions(-)
diff --git a/refs.c b/refs.c
index 7843d3085..9137ac283 100644
--- a/refs.c
+++ b/refs.c
@@ -185,13 +185,20 @@ struct ref_filter {
void *cb_data;
};
-int read_ref_full(const char *refname, int resolve_flags, unsigned char *sha1, int *flags)
+int refs_read_ref_full(struct ref_store *refs, const char *refname,
+ int resolve_flags, unsigned char *sha1, int *flags)
{
- if (resolve_ref_unsafe(refname, resolve_flags, sha1, flags))
+ if (refs_resolve_ref_unsafe(refs, refname, resolve_flags, sha1, flags))
return 0;
return -1;
}
+int read_ref_full(const char *refname, int resolve_flags, unsigned char *sha1, int *flags)
+{
+ return refs_read_ref_full(get_main_ref_store(), refname,
+ resolve_flags, sha1, flags);
+}
+
int read_ref(const char *refname, unsigned char *sha1)
{
return read_ref_full(refname, RESOLVE_REF_READING, sha1, NULL);
@@ -286,34 +293,52 @@ void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, const struct string_li
for_each_rawref(warn_if_dangling_symref, &data);
}
+int refs_for_each_tag_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
+{
+ return refs_for_each_ref_in(refs, "refs/tags/", fn, cb_data);
+}
+
int for_each_tag_ref(each_ref_fn fn, void *cb_data)
{
- return for_each_ref_in("refs/tags/", fn, cb_data);
+ return refs_for_each_tag_ref(get_main_ref_store(), 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);
+ return refs_for_each_tag_ref(get_submodule_ref_store(submodule),
+ fn, cb_data);
+}
+
+int refs_for_each_branch_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
+{
+ return refs_for_each_ref_in(refs, "refs/heads/", 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);
+ return refs_for_each_branch_ref(get_main_ref_store(), 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);
+ return refs_for_each_branch_ref(get_submodule_ref_store(submodule),
+ fn, cb_data);
+}
+
+int refs_for_each_remote_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
+{
+ return refs_for_each_ref_in(refs, "refs/remotes/", 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);
+ return refs_for_each_remote_ref(get_main_ref_store(), 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);
+ return refs_for_each_remote_ref(get_submodule_ref_store(submodule),
+ fn, cb_data);
}
int head_ref_namespaced(each_ref_fn fn, void *cb_data)
@@ -1120,14 +1145,17 @@ const char *find_descendant_ref(const char *dirname,
return NULL;
}
-int rename_ref_available(const char *old_refname, const char *new_refname)
+int refs_rename_ref_available(struct ref_store *refs,
+ const char *old_refname,
+ const char *new_refname)
{
struct string_list skip = STRING_LIST_INIT_NODUP;
struct strbuf err = STRBUF_INIT;
int ok;
string_list_insert(&skip, old_refname);
- ok = !verify_refname_available(new_refname, NULL, &skip, &err);
+ ok = !refs_verify_refname_available(refs, new_refname,
+ NULL, &skip, &err);
if (!ok)
error("%s", err.buf);
@@ -1168,10 +1196,9 @@ int head_ref(each_ref_fn fn, void *cb_data)
* non-zero value, stop the iteration and return that value;
* otherwise, return 0.
*/
-static int do_for_each_ref(const char *submodule, const char *prefix,
+static int do_for_each_ref(struct ref_store *refs, const char *prefix,
each_ref_fn fn, int trim, int flags, void *cb_data)
{
- struct ref_store *refs = get_submodule_ref_store(submodule);
struct ref_iterator *iter;
if (!refs)
@@ -1183,19 +1210,30 @@ static int do_for_each_ref(const char *submodule, const char *prefix,
return do_for_each_ref_iterator(iter, fn, cb_data);
}
+int refs_for_each_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
+{
+ return do_for_each_ref(refs, "", fn, 0, 0, cb_data);
+}
+
int for_each_ref(each_ref_fn fn, void *cb_data)
{
- return do_for_each_ref(NULL, "", fn, 0, 0, cb_data);
+ return refs_for_each_ref(get_main_ref_store(), fn, cb_data);
}
int for_each_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
{
- return do_for_each_ref(submodule, "", fn, 0, 0, cb_data);
+ return refs_for_each_ref(get_submodule_ref_store(submodule), fn, cb_data);
+}
+
+int refs_for_each_ref_in(struct ref_store *refs, const char *prefix,
+ each_ref_fn fn, void *cb_data)
+{
+ return do_for_each_ref(refs, prefix, fn, strlen(prefix), 0, cb_data);
}
int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data)
{
- return do_for_each_ref(NULL, prefix, fn, strlen(prefix), 0, cb_data);
+ return refs_for_each_ref_in(get_main_ref_store(), prefix, fn, cb_data);
}
int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data, unsigned int broken)
@@ -1204,19 +1242,23 @@ int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data, unsig
if (broken)
flag = DO_FOR_EACH_INCLUDE_BROKEN;
- return do_for_each_ref(NULL, prefix, fn, 0, flag, cb_data);
+ return do_for_each_ref(get_main_ref_store(),
+ prefix, fn, 0, flag, cb_data);
}
int for_each_ref_in_submodule(const char *submodule, const char *prefix,
- each_ref_fn fn, void *cb_data)
+ each_ref_fn fn, void *cb_data)
{
- return do_for_each_ref(submodule, prefix, fn, strlen(prefix), 0, cb_data);
+ return refs_for_each_ref_in(get_submodule_ref_store(submodule),
+ prefix, fn, cb_data);
}
int for_each_replace_ref(each_ref_fn fn, void *cb_data)
{
- return do_for_each_ref(NULL, git_replace_ref_base, fn,
- strlen(git_replace_ref_base), 0, cb_data);
+ return do_for_each_ref(get_main_ref_store(),
+ git_replace_ref_base, fn,
+ strlen(git_replace_ref_base),
+ 0, cb_data);
}
int for_each_namespaced_ref(each_ref_fn fn, void *cb_data)
@@ -1224,19 +1266,25 @@ int for_each_namespaced_ref(each_ref_fn fn, void *cb_data)
struct strbuf buf = STRBUF_INIT;
int ret;
strbuf_addf(&buf, "%srefs/", get_git_namespace());
- ret = do_for_each_ref(NULL, buf.buf, fn, 0, 0, cb_data);
+ ret = do_for_each_ref(get_main_ref_store(),
+ buf.buf, fn, 0, 0, cb_data);
strbuf_release(&buf);
return ret;
}
-int for_each_rawref(each_ref_fn fn, void *cb_data)
+int refs_for_each_rawref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
{
- return do_for_each_ref(NULL, "", fn, 0,
+ return do_for_each_ref(refs, "", fn, 0,
DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
}
+int for_each_rawref(each_ref_fn fn, void *cb_data)
+{
+ return refs_for_each_rawref(get_main_ref_store(), fn, cb_data);
+}
+
/* This function needs to return a meaningful errno on failure */
-const char *resolve_ref_recursively(struct ref_store *refs,
+const char *refs_resolve_ref_unsafe(struct ref_store *refs,
const char *refname,
int resolve_flags,
unsigned char *sha1, int *flags)
@@ -1323,7 +1371,7 @@ int refs_init_db(struct strbuf *err)
const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
unsigned char *sha1, int *flags)
{
- return resolve_ref_recursively(get_main_ref_store(), refname,
+ return refs_resolve_ref_unsafe(get_main_ref_store(), refname,
resolve_flags, sha1, flags);
}
@@ -1353,7 +1401,7 @@ int resolve_gitlink_ref(const char *submodule, const char *refname,
if (!refs)
return -1;
- if (!resolve_ref_recursively(refs, refname, 0, sha1, &flags) ||
+ if (!refs_resolve_ref_unsafe(refs, refname, 0, sha1, &flags) ||
is_null_sha1(sha1))
return -1;
return 0;
@@ -1511,27 +1559,42 @@ void base_ref_store_init(struct ref_store *refs,
}
/* backend functions */
+int refs_pack_refs(struct ref_store *refs, unsigned int flags)
+{
+ return refs->be->pack_refs(refs, flags);
+}
+
int pack_refs(unsigned int flags)
{
- struct ref_store *refs = get_main_ref_store();
+ return refs_pack_refs(get_main_ref_store(), flags);
+}
- return refs->be->pack_refs(refs, flags);
+int refs_peel_ref(struct ref_store *refs, const char *refname,
+ unsigned char *sha1)
+{
+ return refs->be->peel_ref(refs, refname, sha1);
}
int peel_ref(const char *refname, unsigned char *sha1)
{
- struct ref_store *refs = get_main_ref_store();
+ return refs_peel_ref(get_main_ref_store(), refname, sha1);
+}
- return refs->be->peel_ref(refs, refname, sha1);
+int refs_create_symref(struct ref_store *refs,
+ const char *ref_target,
+ const char *refs_heads_master,
+ const char *logmsg)
+{
+ return refs->be->create_symref(refs, ref_target,
+ refs_heads_master,
+ logmsg);
}
int create_symref(const char *ref_target, const char *refs_heads_master,
const char *logmsg)
{
- struct ref_store *refs = get_main_ref_store();
-
- return refs->be->create_symref(refs, ref_target, refs_heads_master,
- logmsg);
+ return refs_create_symref(get_main_ref_store(), ref_target,
+ refs_heads_master, logmsg);
}
int ref_transaction_commit(struct ref_transaction *transaction,
@@ -1542,19 +1605,17 @@ int ref_transaction_commit(struct ref_transaction *transaction,
return refs->be->transaction_commit(refs, transaction, err);
}
-int verify_refname_available(const char *refname,
- const struct string_list *extra,
- const struct string_list *skip,
- struct strbuf *err)
+int refs_verify_refname_available(struct ref_store *refs,
+ const char *refname,
+ const struct string_list *extra,
+ const struct string_list *skip,
+ struct strbuf *err)
{
- struct ref_store *refs = get_main_ref_store();
-
return refs->be->verify_refname_available(refs, refname, extra, skip, err);
}
-int for_each_reflog(each_ref_fn fn, void *cb_data)
+int refs_for_each_reflog(struct ref_store *refs, each_ref_fn fn, void *cb_data)
{
- struct ref_store *refs = get_main_ref_store();
struct ref_iterator *iter;
iter = refs->be->reflog_iterator_begin(refs);
@@ -1562,43 +1623,84 @@ int for_each_reflog(each_ref_fn fn, void *cb_data)
return do_for_each_ref_iterator(iter, fn, cb_data);
}
-int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn,
- void *cb_data)
+int for_each_reflog(each_ref_fn fn, void *cb_data)
{
- struct ref_store *refs = get_main_ref_store();
+ return refs_for_each_reflog(get_main_ref_store(), fn, cb_data);
+}
+int refs_for_each_reflog_ent_reverse(struct ref_store *refs,
+ const char *refname,
+ each_reflog_ent_fn fn,
+ void *cb_data)
+{
return refs->be->for_each_reflog_ent_reverse(refs, refname,
fn, cb_data);
}
+int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn,
+ void *cb_data)
+{
+ return refs_for_each_reflog_ent_reverse(get_main_ref_store(),
+ refname, fn, cb_data);
+}
+
+int refs_for_each_reflog_ent(struct ref_store *refs, const char *refname,
+ each_reflog_ent_fn fn, void *cb_data)
+{
+ return refs->be->for_each_reflog_ent(refs, refname, fn, cb_data);
+}
+
int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn,
void *cb_data)
{
- struct ref_store *refs = get_main_ref_store();
+ return refs_for_each_reflog_ent(get_main_ref_store(), refname,
+ fn, cb_data);
+}
- return refs->be->for_each_reflog_ent(refs, refname, fn, cb_data);
+int refs_reflog_exists(struct ref_store *refs, const char *refname)
+{
+ return refs->be->reflog_exists(refs, refname);
}
int reflog_exists(const char *refname)
{
- struct ref_store *refs = get_main_ref_store();
+ return refs_reflog_exists(get_main_ref_store(), refname);
+}
- return refs->be->reflog_exists(refs, refname);
+int refs_create_reflog(struct ref_store *refs, const char *refname,
+ int force_create, struct strbuf *err)
+{
+ return refs->be->create_reflog(refs, refname, force_create, err);
}
int safe_create_reflog(const char *refname, int force_create,
struct strbuf *err)
{
- struct ref_store *refs = get_main_ref_store();
+ return refs_create_reflog(get_main_ref_store(), refname,
+ force_create, err);
+}
- return refs->be->create_reflog(refs, refname, force_create, err);
+int refs_delete_reflog(struct ref_store *refs, const char *refname)
+{
+ return refs->be->delete_reflog(refs, refname);
}
int delete_reflog(const char *refname)
{
- struct ref_store *refs = get_main_ref_store();
+ return refs_delete_reflog(get_main_ref_store(), refname);
+}
- return refs->be->delete_reflog(refs, refname);
+int refs_reflog_expire(struct ref_store *refs,
+ const char *refname, const unsigned char *sha1,
+ unsigned int flags,
+ reflog_expiry_prepare_fn prepare_fn,
+ reflog_expiry_should_prune_fn should_prune_fn,
+ reflog_expiry_cleanup_fn cleanup_fn,
+ void *policy_cb_data)
+{
+ return refs->be->reflog_expire(refs, refname, sha1, flags,
+ prepare_fn, should_prune_fn,
+ cleanup_fn, policy_cb_data);
}
int reflog_expire(const char *refname, const unsigned char *sha1,
@@ -1608,11 +1710,10 @@ int reflog_expire(const char *refname, const unsigned char *sha1,
reflog_expiry_cleanup_fn cleanup_fn,
void *policy_cb_data)
{
- struct ref_store *refs = get_main_ref_store();
-
- return refs->be->reflog_expire(refs, refname, sha1, flags,
- prepare_fn, should_prune_fn,
- cleanup_fn, policy_cb_data);
+ return refs_reflog_expire(get_main_ref_store(),
+ refname, sha1, flags,
+ prepare_fn, should_prune_fn,
+ cleanup_fn, policy_cb_data);
}
int initial_ref_transaction_commit(struct ref_transaction *transaction,
@@ -1623,16 +1724,24 @@ int initial_ref_transaction_commit(struct ref_transaction *transaction,
return refs->be->initial_transaction_commit(refs, transaction, err);
}
-int delete_refs(struct string_list *refnames, unsigned int flags)
+int refs_delete_refs(struct ref_store *refs, struct string_list *refnames,
+ unsigned int flags)
{
- struct ref_store *refs = get_main_ref_store();
-
return refs->be->delete_refs(refs, refnames, flags);
}
-int rename_ref(const char *oldref, const char *newref, const char *logmsg)
+int delete_refs(struct string_list *refnames, unsigned int flags)
{
- struct ref_store *refs = get_main_ref_store();
+ return refs_delete_refs(get_main_ref_store(), refnames, flags);
+}
+int refs_rename_ref(struct ref_store *refs, const char *oldref,
+ const char *newref, const char *logmsg)
+{
return refs->be->rename_ref(refs, oldref, newref, logmsg);
}
+
+int rename_ref(const char *oldref, const char *newref, const char *logmsg)
+{
+ return refs_rename_ref(get_main_ref_store(), oldref, newref, logmsg);
+}
diff --git a/refs.h b/refs.h
index 2efba6ba9..70d4eb87c 100644
--- a/refs.h
+++ b/refs.h
@@ -58,16 +58,47 @@ struct string_list;
#define RESOLVE_REF_NO_RECURSE 0x02
#define RESOLVE_REF_ALLOW_BAD_NAME 0x04
+const char *refs_resolve_ref_unsafe(struct ref_store *refs,
+ const char *refname,
+ int resolve_flags,
+ unsigned char *sha1,
+ int *flags);
const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
unsigned char *sha1, int *flags);
char *resolve_refdup(const char *refname, int resolve_flags,
unsigned char *sha1, int *flags);
+int refs_read_ref_full(struct ref_store *refs, const char *refname,
+ int resolve_flags, unsigned char *sha1, int *flags);
int read_ref_full(const char *refname, int resolve_flags,
unsigned char *sha1, int *flags);
int read_ref(const char *refname, unsigned char *sha1);
+/*
+ * 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".
+ *
+ * extras and skip must be sorted.
+ */
+
+int refs_verify_refname_available(struct ref_store *refs,
+ const char *refname,
+ const struct string_list *extra,
+ const struct string_list *skip,
+ struct strbuf *err);
+
int ref_exists(const char *refname);
int should_autocreate_reflog(const char *refname);
@@ -84,6 +115,8 @@ extern int refs_init_db(struct strbuf *err);
* Symbolic references are considered unpeelable, even if they
* ultimately resolve to a peelable tag.
*/
+int refs_peel_ref(struct ref_store *refs, const char *refname,
+ unsigned char *sha1);
int peel_ref(const char *refname, unsigned char *sha1);
/**
@@ -196,6 +229,17 @@ typedef int each_ref_fn(const char *refname,
* modifies the reference also returns a nonzero value to immediately
* stop the iteration.
*/
+int refs_for_each_ref(struct ref_store *refs,
+ each_ref_fn fn, void *cb_data);
+int refs_for_each_ref_in(struct ref_store *refs, const char *prefix,
+ each_ref_fn fn, void *cb_data);
+int refs_for_each_tag_ref(struct ref_store *refs,
+ each_ref_fn fn, void *cb_data);
+int refs_for_each_branch_ref(struct ref_store *refs,
+ each_ref_fn fn, void *cb_data);
+int refs_for_each_remote_ref(struct ref_store *refs,
+ each_ref_fn fn, void *cb_data);
+
int head_ref(each_ref_fn fn, void *cb_data);
int for_each_ref(each_ref_fn fn, void *cb_data);
int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data);
@@ -225,6 +269,7 @@ int head_ref_namespaced(each_ref_fn fn, void *cb_data);
int for_each_namespaced_ref(each_ref_fn fn, void *cb_data);
/* can be used to learn about broken ref and symref */
+int refs_for_each_rawref(struct ref_store *refs, each_ref_fn fn, void *cb_data);
int for_each_rawref(each_ref_fn fn, void *cb_data);
static inline const char *has_glob_specials(const char *pattern)
@@ -248,6 +293,7 @@ void warn_dangling_symrefs(FILE *fp, const char *msg_fmt,
* Write a packed-refs file for the current repository.
* flags: Combination of the above PACK_REFS_* flags.
*/
+int refs_pack_refs(struct ref_store *refs, unsigned int flags);
int pack_refs(unsigned int flags);
/*
@@ -263,6 +309,8 @@ int pack_refs(unsigned int flags);
/*
* Setup reflog before using. Fill in err and return -1 on failure.
*/
+int refs_create_reflog(struct ref_store *refs, const char *refname,
+ int force_create, struct strbuf *err);
int safe_create_reflog(const char *refname, int force_create, struct strbuf *err);
/** Reads log for the value of ref during at_time. **/
@@ -272,6 +320,7 @@ int read_ref_at(const char *refname, unsigned int flags,
unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt);
/** Check if a particular reflog exists */
+int refs_reflog_exists(struct ref_store *refs, const char *refname);
int reflog_exists(const char *refname);
/*
@@ -290,9 +339,12 @@ int delete_ref(const char *refname, const unsigned char *old_sha1,
* an all-or-nothing transaction). flags is passed through to
* ref_transaction_delete().
*/
+int refs_delete_refs(struct ref_store *refs, struct string_list *refnames,
+ unsigned int flags);
int delete_refs(struct string_list *refnames, unsigned int flags);
/** Delete a reflog */
+int refs_delete_reflog(struct ref_store *refs, const char *refname);
int delete_reflog(const char *refname);
/* iterate over reflog entries */
@@ -301,6 +353,12 @@ typedef int each_reflog_ent_fn(
const char *committer, unsigned long timestamp,
int tz, const char *msg, void *cb_data);
+int refs_for_each_reflog_ent(struct ref_store *refs, const char *refname,
+ each_reflog_ent_fn fn, void *cb_data);
+int refs_for_each_reflog_ent_reverse(struct ref_store *refs,
+ const char *refname,
+ each_reflog_ent_fn fn,
+ void *cb_data);
int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn, void *cb_data);
int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn, void *cb_data);
@@ -308,6 +366,7 @@ int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn, void
* Calls the specified function for each reflog file until it returns nonzero,
* and returns the value
*/
+int refs_for_each_reflog(struct ref_store *refs, each_ref_fn fn, void *cb_data);
int for_each_reflog(each_ref_fn fn, void *cb_data);
#define REFNAME_ALLOW_ONELEVEL 1
@@ -328,8 +387,12 @@ const char *prettify_refname(const char *refname);
char *shorten_unambiguous_ref(const char *refname, int strict);
/** rename ref, return 0 on success **/
+int refs_rename_ref(struct ref_store *refs, const char *oldref,
+ const char *newref, const char *logmsg);
int rename_ref(const char *oldref, const char *newref, const char *logmsg);
+int refs_create_symref(struct ref_store *refs, const char *refname,
+ const char *target, const char *logmsg);
int create_symref(const char *refname, const char *target, const char *logmsg);
/*
@@ -551,6 +614,14 @@ typedef void reflog_expiry_cleanup_fn(void *cb_data);
* enum expire_reflog_flags. The three function pointers are described
* above. On success, return zero.
*/
+int refs_reflog_expire(struct ref_store *refs,
+ const char *refname,
+ const unsigned char *sha1,
+ unsigned int flags,
+ reflog_expiry_prepare_fn prepare_fn,
+ reflog_expiry_should_prune_fn should_prune_fn,
+ reflog_expiry_cleanup_fn cleanup_fn,
+ void *policy_cb_data);
int reflog_expire(const char *refname, const unsigned char *sha1,
unsigned int flags,
reflog_expiry_prepare_fn prepare_fn,
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 474d1027c..dafddefd3 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1320,7 +1320,7 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir)
create_dir_entry(refs, refname.buf,
refname.len, 1));
} else {
- if (!resolve_ref_recursively(&refs->base,
+ if (!refs_resolve_ref_unsafe(&refs->base,
refname.buf,
RESOLVE_REF_READING,
sha1, &flag)) {
@@ -1629,7 +1629,8 @@ static int lock_raw_ref(struct files_ref_store *refs,
* another reference such as "refs/foo". There is no
* reason to expect this error to be transitory.
*/
- if (verify_refname_available(refname, extras, skip, err)) {
+ if (refs_verify_refname_available(&refs->base, refname,
+ extras, skip, err)) {
if (mustexist) {
/*
* To the user the relevant error is
@@ -2671,7 +2672,7 @@ static int files_rename_ref(struct ref_store *ref_store,
if (flag & REF_ISSYMREF)
return error("refname %s is a symbolic ref, renaming it is not supported",
oldrefname);
- if (!rename_ref_available(oldrefname, newrefname))
+ if (!refs_rename_ref_available(&refs->base, oldrefname, newrefname))
return 1;
files_reflog_path(refs, &sb_oldref, oldrefname);
@@ -4055,9 +4056,9 @@ static int files_initial_transaction_commit(struct ref_store *ref_store,
if ((update->flags & REF_HAVE_OLD) &&
!is_null_sha1(update->old_sha1))
die("BUG: initial ref transaction with old_sha1 set");
- if (verify_refname_available(update->refname,
- &affected_refnames, NULL,
- err)) {
+ if (refs_verify_refname_available(&refs->base, update->refname,
+ &affected_refnames, NULL,
+ err)) {
ret = TRANSACTION_NAME_CONFLICT;
goto cleanup;
}
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index f20dde39e..5f26208c2 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -112,28 +112,6 @@ enum peel_status {
enum peel_status peel_object(const unsigned char *name, unsigned char *sha1);
/*
- * 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".
- *
- * extras and skip must be sorted.
- */
-int verify_refname_available(const char *newname,
- const struct string_list *extras,
- const struct string_list *skip,
- struct strbuf *err);
-
-/*
* 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.
@@ -252,7 +230,9 @@ const char *find_descendant_ref(const char *dirname,
* processes (though rename_ref() catches some races that might get by
* this check).
*/
-int rename_ref_available(const char *old_refname, const char *new_refname);
+int refs_rename_ref_available(struct ref_store *refs,
+ const char *old_refname,
+ const char *new_refname);
/* We allow "recursive" symbolic refs. Only within reason, though */
#define SYMREF_MAXDEPTH 5
@@ -646,9 +626,4 @@ struct ref_store {
void base_ref_store_init(struct ref_store *refs,
const struct ref_storage_be *be);
-const char *resolve_ref_recursively(struct ref_store *refs,
- const char *refname,
- int resolve_flags,
- unsigned char *sha1, int *flags);
-
#endif /* REFS_REFS_INTERNAL_H */
--
2.11.0.157.gd943d85
^ permalink raw reply related
* [PATCH v5 19/24] refs: new transaction related ref-store api
From: Nguyễn Thái Ngọc Duy @ 2017-02-22 14:04 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Michael Haggerty, Johannes Schindelin,
Ramsay Jones, Stefan Beller, novalis,
Nguyễn Thái Ngọc Duy
In-Reply-To: <20170222140450.30886-1-pclouds@gmail.com>
The transaction struct now takes a ref store at creation and will
operate on that ref store alone.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
refs.c | 54 ++++++++++++++++++++++++++++++++++++++++------------
refs.h | 8 ++++++++
refs/refs-internal.h | 1 +
3 files changed, 51 insertions(+), 12 deletions(-)
diff --git a/refs.c b/refs.c
index 9137ac283..851b5e125 100644
--- a/refs.c
+++ b/refs.c
@@ -618,16 +618,19 @@ static int delete_pseudoref(const char *pseudoref, const unsigned char *old_sha1
return 0;
}
-int delete_ref(const char *refname, const unsigned char *old_sha1,
- unsigned int flags)
+int refs_delete_ref(struct ref_store *refs, 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)
+ if (ref_type(refname) == REF_TYPE_PSEUDOREF) {
+ assert(refs == get_main_ref_store());
return delete_pseudoref(refname, old_sha1);
+ }
- transaction = ref_transaction_begin(&err);
+ transaction = ref_store_transaction_begin(refs, &err);
if (!transaction ||
ref_transaction_delete(transaction, refname, old_sha1,
flags, NULL, &err) ||
@@ -642,6 +645,13 @@ int delete_ref(const char *refname, const unsigned char *old_sha1,
return 0;
}
+int delete_ref(const char *refname, const unsigned char *old_sha1,
+ unsigned int flags)
+{
+ return refs_delete_ref(get_main_ref_store(), refname,
+ old_sha1, flags);
+}
+
int copy_reflog_msg(char *buf, const char *msg)
{
char *cp = buf;
@@ -801,11 +811,20 @@ int read_ref_at(const char *refname, unsigned int flags, unsigned long at_time,
return 1;
}
-struct ref_transaction *ref_transaction_begin(struct strbuf *err)
+struct ref_transaction *ref_store_transaction_begin(struct ref_store *refs,
+ struct strbuf *err)
{
+ struct ref_transaction *tr;
assert(err);
- return xcalloc(1, sizeof(struct ref_transaction));
+ tr = xcalloc(1, sizeof(struct ref_transaction));
+ tr->ref_store = refs;
+ return tr;
+}
+
+struct ref_transaction *ref_transaction_begin(struct strbuf *err)
+{
+ return ref_store_transaction_begin(get_main_ref_store(), err);
}
void ref_transaction_free(struct ref_transaction *transaction)
@@ -922,18 +941,20 @@ int update_ref_oid(const char *msg, const char *refname,
old_oid ? old_oid->hash : NULL, flags, onerr);
}
-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)
+int refs_update_ref(struct ref_store *refs, 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) {
+ assert(refs == get_main_ref_store());
ret = write_pseudoref(refname, new_sha1, old_sha1, &err);
} else {
- t = ref_transaction_begin(&err);
+ t = ref_store_transaction_begin(refs, &err);
if (!t ||
ref_transaction_update(t, refname, new_sha1, old_sha1,
flags, msg, &err) ||
@@ -964,6 +985,15 @@ int update_ref(const char *msg, const char *refname,
return 0;
}
+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)
+{
+ return refs_update_ref(get_main_ref_store(), msg, refname, new_sha1,
+ old_sha1, flags, onerr);
+}
+
char *shorten_unambiguous_ref(const char *refname, int strict)
{
int i;
@@ -1600,7 +1630,7 @@ int create_symref(const char *ref_target, const char *refs_heads_master,
int ref_transaction_commit(struct ref_transaction *transaction,
struct strbuf *err)
{
- struct ref_store *refs = get_main_ref_store();
+ struct ref_store *refs = transaction->ref_store;
return refs->be->transaction_commit(refs, transaction, err);
}
@@ -1719,7 +1749,7 @@ int reflog_expire(const char *refname, const unsigned char *sha1,
int initial_ref_transaction_commit(struct ref_transaction *transaction,
struct strbuf *err)
{
- struct ref_store *refs = get_main_ref_store();
+ struct ref_store *refs = transaction->ref_store;
return refs->be->initial_transaction_commit(refs, transaction, err);
}
diff --git a/refs.h b/refs.h
index 70d4eb87c..342cecd23 100644
--- a/refs.h
+++ b/refs.h
@@ -330,6 +330,9 @@ int reflog_exists(const char *refname);
* exists, regardless of its old value. It is an error for old_sha1 to
* be NULL_SHA1. flags is passed through to ref_transaction_delete().
*/
+int refs_delete_ref(struct ref_store *refs, const char *refname,
+ const unsigned char *old_sha1,
+ unsigned int flags);
int delete_ref(const char *refname, const unsigned char *old_sha1,
unsigned int flags);
@@ -414,6 +417,8 @@ enum action_on_err {
* Begin a reference transaction. The reference transaction must
* be freed by calling ref_transaction_free().
*/
+struct ref_transaction *ref_store_transaction_begin(struct ref_store *refs,
+ struct strbuf *err);
struct ref_transaction *ref_transaction_begin(struct strbuf *err);
/*
@@ -548,6 +553,9 @@ void ref_transaction_free(struct ref_transaction *transaction);
* ref_transaction_update(). Handle errors as requested by the `onerr`
* argument.
*/
+int refs_update_ref(struct ref_store *refs, const char *msg, const char *refname,
+ const unsigned char *new_sha1, const unsigned char *old_sha1,
+ unsigned int flags, enum action_on_err onerr);
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);
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index 5f26208c2..690498698 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -200,6 +200,7 @@ enum ref_transaction_state {
* as atomically as possible. This structure is opaque to callers.
*/
struct ref_transaction {
+ struct ref_store *ref_store;
struct ref_update **updates;
size_t alloc;
size_t nr;
--
2.11.0.157.gd943d85
^ permalink raw reply related
* [PATCH v5 20/24] files-backend: avoid ref api targetting main ref store
From: Nguyễn Thái Ngọc Duy @ 2017-02-22 14:04 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Michael Haggerty, Johannes Schindelin,
Ramsay Jones, Stefan Beller, novalis,
Nguyễn Thái Ngọc Duy
In-Reply-To: <20170222140450.30886-1-pclouds@gmail.com>
A small step towards making files-backend works as a non-main ref store
using the newly added store-aware API.
For the record, `join` and `nm` on refs.o and files-backend.o tell me
that files-backend no longer uses functions that defaults to
get_main_ref_store().
I'm not yet comfortable at the idea of removing
files_assert_main_repository() (or converting REF_STORE_MAIN to
REF_STORE_WRITE). More staring and testing is required before that can
happen. Well, except peel_ref(). I'm pretty sure that function is safe.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
refs/files-backend.c | 85 ++++++++++++++++++++++++++++++----------------------
1 file changed, 49 insertions(+), 36 deletions(-)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index dafddefd3..09c280fd3 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1836,8 +1836,6 @@ static int files_peel_ref(struct ref_store *ref_store,
int flag;
unsigned char base[20];
- files_assert_main_repository(refs, "peel_ref");
-
if (current_ref_iter && current_ref_iter->refname == refname) {
struct object_id peeled;
@@ -1847,7 +1845,8 @@ static int files_peel_ref(struct ref_store *ref_store,
return 0;
}
- if (read_ref_full(refname, RESOLVE_REF_READING, base, &flag))
+ if (refs_read_ref_full(ref_store, refname,
+ RESOLVE_REF_READING, base, &flag))
return -1;
/*
@@ -2017,15 +2016,15 @@ static struct ref_iterator *files_ref_iterator_begin(
* on success. On error, write an error message to err, set errno, and
* return a negative value.
*/
-static int verify_lock(struct ref_lock *lock,
+static int verify_lock(struct ref_store *ref_store, struct ref_lock *lock,
const unsigned char *old_sha1, int mustexist,
struct strbuf *err)
{
assert(err);
- if (read_ref_full(lock->ref_name,
- mustexist ? RESOLVE_REF_READING : 0,
- lock->old_oid.hash, NULL)) {
+ if (refs_read_ref_full(ref_store, lock->ref_name,
+ mustexist ? RESOLVE_REF_READING : 0,
+ lock->old_oid.hash, NULL)) {
if (old_sha1) {
int save_errno = errno;
strbuf_addf(err, "can't verify ref '%s'", lock->ref_name);
@@ -2094,8 +2093,9 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs,
resolve_flags |= RESOLVE_REF_ALLOW_BAD_NAME;
files_refname_path(refs, &ref_file, refname);
- resolved = !!resolve_ref_unsafe(refname, resolve_flags,
- lock->old_oid.hash, type);
+ resolved = !!refs_resolve_ref_unsafe(&refs->base,
+ refname, resolve_flags,
+ lock->old_oid.hash, type);
if (!resolved && errno == EISDIR) {
/*
* we are trying to lock foo but we used to
@@ -2112,8 +2112,9 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs,
refname);
goto error_return;
}
- resolved = !!resolve_ref_unsafe(refname, resolve_flags,
- lock->old_oid.hash, type);
+ resolved = !!refs_resolve_ref_unsafe(&refs->base,
+ refname, resolve_flags,
+ lock->old_oid.hash, type);
}
if (!resolved) {
last_errno = errno;
@@ -2151,7 +2152,7 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs,
goto error_return;
}
- if (verify_lock(lock, old_sha1, mustexist, err)) {
+ if (verify_lock(&refs->base, lock, old_sha1, mustexist, err)) {
last_errno = errno;
goto error_return;
}
@@ -2406,7 +2407,7 @@ static void try_remove_empty_parents(struct files_ref_store *refs,
}
/* make sure nobody touched the ref, and unlink */
-static void prune_ref(struct ref_to_prune *r)
+static void prune_ref(struct files_ref_store *refs, struct ref_to_prune *r)
{
struct ref_transaction *transaction;
struct strbuf err = STRBUF_INIT;
@@ -2414,7 +2415,7 @@ static void prune_ref(struct ref_to_prune *r)
if (check_refname_format(r->name, 0))
return;
- transaction = ref_transaction_begin(&err);
+ transaction = ref_store_transaction_begin(&refs->base, &err);
if (!transaction ||
ref_transaction_delete(transaction, r->name, r->sha1,
REF_ISPRUNING | REF_NODEREF, NULL, &err) ||
@@ -2428,10 +2429,10 @@ static void prune_ref(struct ref_to_prune *r)
strbuf_release(&err);
}
-static void prune_refs(struct ref_to_prune *r)
+static void prune_refs(struct files_ref_store *refs, struct ref_to_prune *r)
{
while (r) {
- prune_ref(r);
+ prune_ref(refs, r);
r = r->next;
}
}
@@ -2455,7 +2456,7 @@ static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)
if (commit_packed_refs(refs))
die_errno("unable to overwrite old ref-pack file");
- prune_refs(cbdata.ref_to_prune);
+ prune_refs(refs, cbdata.ref_to_prune);
return 0;
}
@@ -2547,7 +2548,7 @@ static int files_delete_refs(struct ref_store *ref_store,
for (i = 0; i < refnames->nr; i++) {
const char *refname = refnames->items[i].string;
- if (delete_ref(refname, NULL, flags))
+ if (refs_delete_ref(&refs->base, refname, NULL, flags))
result |= error(_("could not remove reference %s"), refname);
}
@@ -2665,8 +2666,9 @@ static int files_rename_ref(struct ref_store *ref_store,
if (log && S_ISLNK(loginfo.st_mode))
return error("reflog for %s is a symlink", oldrefname);
- if (!resolve_ref_unsafe(oldrefname, RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
- orig_sha1, &flag))
+ if (!refs_resolve_ref_unsafe(&refs->base, oldrefname,
+ RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
+ orig_sha1, &flag))
return error("refname %s not found", oldrefname);
if (flag & REF_ISSYMREF)
@@ -2684,7 +2686,7 @@ static int files_rename_ref(struct ref_store *ref_store,
return error("unable to move logfile logs/%s to logs/"TMP_RENAMED_LOG": %s",
oldrefname, strerror(errno));
- if (delete_ref(oldrefname, orig_sha1, REF_NODEREF)) {
+ if (refs_delete_ref(&refs->base, oldrefname, orig_sha1, REF_NODEREF)) {
error("unable to delete old %s", oldrefname);
goto rollback;
}
@@ -2696,9 +2698,10 @@ static int files_rename_ref(struct ref_store *ref_store,
* the safety anyway; we want to delete the reference whatever
* its current value.
*/
- if (!read_ref_full(newrefname, RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
- sha1, NULL) &&
- delete_ref(newrefname, NULL, REF_NODEREF)) {
+ if (!refs_read_ref_full(&refs->base, newrefname,
+ RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
+ sha1, NULL) &&
+ refs_delete_ref(&refs->base, newrefname, NULL, REF_NODEREF)) {
if (errno == EISDIR) {
struct strbuf path = STRBUF_INIT;
int result;
@@ -3054,8 +3057,9 @@ static int commit_ref_update(struct files_ref_store *refs,
int head_flag;
const char *head_ref;
- head_ref = resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
- head_sha1, &head_flag);
+ head_ref = refs_resolve_ref_unsafe(&refs->base, "HEAD",
+ RESOLVE_REF_READING,
+ head_sha1, &head_flag);
if (head_ref && (head_flag & REF_ISSYMREF) &&
!strcmp(head_ref, lock->ref_name)) {
struct strbuf log_err = STRBUF_INIT;
@@ -3099,7 +3103,9 @@ static void update_symref_reflog(struct files_ref_store *refs,
{
struct strbuf err = STRBUF_INIT;
unsigned char new_sha1[20];
- if (logmsg && !read_ref(target, new_sha1) &&
+ if (logmsg &&
+ !refs_read_ref_full(&refs->base, target,
+ RESOLVE_REF_READING, new_sha1, NULL) &&
files_log_ref_write(refs, refname, lock->old_oid.hash,
new_sha1, logmsg, 0, &err)) {
error("%s", err.buf);
@@ -3403,6 +3409,7 @@ static int files_for_each_reflog_ent(struct ref_store *ref_store,
struct files_reflog_iterator {
struct ref_iterator base;
+ struct ref_store *ref_store;
struct dir_iterator *dir_iterator;
struct object_id oid;
};
@@ -3424,8 +3431,9 @@ static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator)
if (ends_with(diter->basename, ".lock"))
continue;
- if (read_ref_full(diter->relative_path, 0,
- iter->oid.hash, &flags)) {
+ if (refs_read_ref_full(iter->ref_store,
+ diter->relative_path, 0,
+ iter->oid.hash, &flags)) {
error("bad ref for %s", diter->path.buf);
continue;
}
@@ -3479,6 +3487,7 @@ static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_st
base_ref_iterator_init(ref_iterator, &files_reflog_iterator_vtable);
files_reflog_path(refs, &sb, NULL);
iter->dir_iterator = dir_iterator_begin(sb.buf);
+ iter->ref_store = ref_store;
strbuf_release(&sb);
return ref_iterator;
}
@@ -3718,8 +3727,9 @@ static int lock_ref_for_update(struct files_ref_store *refs,
* the transaction, so we have to read it here
* to record and possibly check old_sha1:
*/
- if (read_ref_full(referent.buf, 0,
- lock->old_oid.hash, NULL)) {
+ if (refs_read_ref_full(&refs->base,
+ referent.buf, 0,
+ lock->old_oid.hash, NULL)) {
if (update->flags & REF_HAVE_OLD) {
strbuf_addf(err, "cannot lock ref '%s': "
"error reading reference",
@@ -3873,8 +3883,10 @@ static int files_transaction_commit(struct ref_store *ref_store,
* head_ref within the transaction, then split_head_update()
* arranges for the reflog of HEAD to be updated, too.
*/
- head_ref = resolve_refdup("HEAD", RESOLVE_REF_NO_RECURSE,
- head_oid.hash, &head_type);
+ head_ref = (char *)refs_resolve_ref_unsafe(ref_store, "HEAD",
+ RESOLVE_REF_NO_RECURSE,
+ head_oid.hash, &head_type);
+ head_ref = xstrdup_or_null(head_ref);
if (head_ref && !(head_type & REF_ISSYMREF)) {
free(head_ref);
@@ -4047,7 +4059,8 @@ static int files_initial_transaction_commit(struct ref_store *ref_store,
* so here we really only check that none of the references
* that we are creating already exists.
*/
- if (for_each_rawref(ref_present, &affected_refnames))
+ if (refs_for_each_rawref(&refs->base, ref_present,
+ &affected_refnames))
die("BUG: initial ref transaction called with existing refs");
for (i = 0; i < transaction->nr; i++) {
@@ -4166,7 +4179,7 @@ static int files_reflog_expire(struct ref_store *ref_store,
strbuf_release(&err);
return -1;
}
- if (!reflog_exists(refname)) {
+ if (!refs_reflog_exists(ref_store, refname)) {
unlock_ref(lock);
return 0;
}
@@ -4197,7 +4210,7 @@ static int files_reflog_expire(struct ref_store *ref_store,
}
(*prepare_fn)(refname, sha1, cb.policy_cb);
- for_each_reflog_ent(refname, expire_reflog_ent, &cb);
+ refs_for_each_reflog_ent(ref_store, refname, expire_reflog_ent, &cb);
(*cleanup_fn)(cb.policy_cb);
if (!(flags & EXPIRE_REFLOGS_DRY_RUN)) {
--
2.11.0.157.gd943d85
^ permalink raw reply related
* [PATCH v5 21/24] refs: delete pack_refs() in favor of refs_pack_refs()
From: Nguyễn Thái Ngọc Duy @ 2017-02-22 14:04 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Michael Haggerty, Johannes Schindelin,
Ramsay Jones, Stefan Beller, novalis,
Nguyễn Thái Ngọc Duy
In-Reply-To: <20170222140450.30886-1-pclouds@gmail.com>
It only has one caller, not worth keeping just for convenience.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
builtin/pack-refs.c | 2 +-
refs.c | 5 -----
refs.h | 1 -
3 files changed, 1 insertion(+), 7 deletions(-)
diff --git a/builtin/pack-refs.c b/builtin/pack-refs.c
index 39f9a55d1..b106a392a 100644
--- a/builtin/pack-refs.c
+++ b/builtin/pack-refs.c
@@ -17,5 +17,5 @@ int cmd_pack_refs(int argc, const char **argv, const char *prefix)
};
if (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0))
usage_with_options(pack_refs_usage, opts);
- return pack_refs(flags);
+ return refs_pack_refs(get_main_ref_store(), flags);
}
diff --git a/refs.c b/refs.c
index 851b5e125..6efe5957d 100644
--- a/refs.c
+++ b/refs.c
@@ -1594,11 +1594,6 @@ int refs_pack_refs(struct ref_store *refs, unsigned int flags)
return refs->be->pack_refs(refs, flags);
}
-int pack_refs(unsigned int flags)
-{
- return refs_pack_refs(get_main_ref_store(), flags);
-}
-
int refs_peel_ref(struct ref_store *refs, const char *refname,
unsigned char *sha1)
{
diff --git a/refs.h b/refs.h
index 342cecd23..1af41eaef 100644
--- a/refs.h
+++ b/refs.h
@@ -294,7 +294,6 @@ void warn_dangling_symrefs(FILE *fp, const char *msg_fmt,
* flags: Combination of the above PACK_REFS_* flags.
*/
int refs_pack_refs(struct ref_store *refs, unsigned int flags);
-int pack_refs(unsigned int flags);
/*
* Flags controlling ref_transaction_update(), ref_transaction_create(), etc.
--
2.11.0.157.gd943d85
^ permalink raw reply related
* [PATCH v5 22/24] t/helper: add test-ref-store to test ref-store functions
From: Nguyễn Thái Ngọc Duy @ 2017-02-22 14:04 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Michael Haggerty, Johannes Schindelin,
Ramsay Jones, Stefan Beller, novalis,
Nguyễn Thái Ngọc Duy
In-Reply-To: <20170222140450.30886-1-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
Makefile | 1 +
t/helper/.gitignore | 1 +
t/helper/test-ref-store.c (new) | 274 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 276 insertions(+)
create mode 100644 t/helper/test-ref-store.c
diff --git a/Makefile b/Makefile
index 8e4081e06..d62d64623 100644
--- a/Makefile
+++ b/Makefile
@@ -624,6 +624,7 @@ TEST_PROGRAMS_NEED_X += test-parse-options
TEST_PROGRAMS_NEED_X += test-path-utils
TEST_PROGRAMS_NEED_X += test-prio-queue
TEST_PROGRAMS_NEED_X += test-read-cache
+TEST_PROGRAMS_NEED_X += test-ref-store
TEST_PROGRAMS_NEED_X += test-regex
TEST_PROGRAMS_NEED_X += test-revision-walking
TEST_PROGRAMS_NEED_X += test-run-command
diff --git a/t/helper/.gitignore b/t/helper/.gitignore
index d6e8b3679..5f68aa8f8 100644
--- a/t/helper/.gitignore
+++ b/t/helper/.gitignore
@@ -19,6 +19,7 @@
/test-path-utils
/test-prio-queue
/test-read-cache
+/test-ref-store
/test-regex
/test-revision-walking
/test-run-command
diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c
new file mode 100644
index 000000000..c4c670acd
--- /dev/null
+++ b/t/helper/test-ref-store.c
@@ -0,0 +1,274 @@
+#include "cache.h"
+#include "refs.h"
+
+static const char *notnull(const char *arg, const char *name)
+{
+ if (!arg)
+ die("%s required", name);
+ return arg;
+}
+
+static unsigned int arg_flags(const char *arg, const char *name)
+{
+ return atoi(notnull(arg, name));
+}
+
+static const char **get_store(const char **argv, struct ref_store **refs)
+{
+ const char *gitdir;
+
+ if (!argv[0]) {
+ die("ref store required");
+ } else if (!strcmp(argv[0], "main")) {
+ *refs = get_main_ref_store();
+ } else if (skip_prefix(argv[0], "submodule:", &gitdir)) {
+ struct strbuf sb = STRBUF_INIT;
+ int ret;
+
+ ret = strbuf_git_path_submodule(&sb, gitdir, "objects/");
+ if (ret)
+ die("strbuf_git_path_submodule failed: %d", ret);
+ add_to_alternates_memory(sb.buf);
+ strbuf_release(&sb);
+
+ *refs = get_submodule_ref_store(gitdir);
+ } else
+ die("unknown backend %s", argv[0]);
+
+ if (!*refs)
+ die("no ref store");
+
+ /* consume store-specific optional arguments if needed */
+
+ return argv + 1;
+}
+
+
+static int cmd_pack_refs(struct ref_store *refs, const char **argv)
+{
+ unsigned int flags = arg_flags(*argv++, "flags");
+
+ return refs_pack_refs(refs, flags);
+}
+
+static int cmd_peel_ref(struct ref_store *refs, const char **argv)
+{
+ const char *refname = notnull(*argv++, "refname");
+ unsigned char sha1[20];
+ int ret;
+
+ ret = refs_peel_ref(refs, refname, sha1);
+ if (!ret)
+ puts(sha1_to_hex(sha1));
+ return ret;
+}
+
+static int cmd_create_symref(struct ref_store *refs, const char **argv)
+{
+ const char *refname = notnull(*argv++, "refname");
+ const char *target = notnull(*argv++, "target");
+ const char *logmsg = *argv++;
+
+ return refs_create_symref(refs, refname, target, logmsg);
+}
+
+static int cmd_delete_refs(struct ref_store *refs, const char **argv)
+{
+ unsigned int flags = arg_flags(*argv++, "flags");
+ struct string_list refnames = STRING_LIST_INIT_NODUP;
+
+ while (*argv)
+ string_list_append(&refnames, *argv++);
+
+ return refs_delete_refs(refs, &refnames, flags);
+}
+
+static int cmd_rename_ref(struct ref_store *refs, const char **argv)
+{
+ const char *oldref = notnull(*argv++, "oldref");
+ const char *newref = notnull(*argv++, "newref");
+ const char *logmsg = *argv++;
+
+ return refs_rename_ref(refs, oldref, newref, logmsg);
+}
+
+static int each_ref(const char *refname, const struct object_id *oid,
+ int flags, void *cb_data)
+{
+ printf("%s %s 0x%x\n", oid_to_hex(oid), refname, flags);
+ return 0;
+}
+
+static int cmd_for_each_ref(struct ref_store *refs, const char **argv)
+{
+ const char *prefix = notnull(*argv++, "prefix");
+
+ return refs_for_each_ref_in(refs, prefix, each_ref, NULL);
+}
+
+static int cmd_resolve_ref(struct ref_store *refs, const char **argv)
+{
+ unsigned char sha1[20];
+ const char *refname = notnull(*argv++, "refname");
+ int resolve_flags = arg_flags(*argv++, "resolve-flags");
+ int flags;
+ const char *ref;
+
+ ref = refs_resolve_ref_unsafe(refs, refname, resolve_flags,
+ sha1, &flags);
+ printf("%s %s 0x%x\n", sha1_to_hex(sha1), ref, flags);
+ return ref ? 0 : 1;
+}
+
+static int cmd_verify_ref(struct ref_store *refs, const char **argv)
+{
+ const char *refname = notnull(*argv++, "refname");
+ struct strbuf err = STRBUF_INIT;
+ int ret;
+
+ ret = refs_verify_refname_available(refs, refname, NULL, NULL, &err);
+ if (err.len)
+ puts(err.buf);
+ return ret;
+}
+
+static int cmd_for_each_reflog(struct ref_store *refs, const char **argv)
+{
+ return refs_for_each_reflog(refs, each_ref, NULL);
+}
+
+static int each_reflog(unsigned char *old_sha1, unsigned char *new_sha1,
+ const char *committer, unsigned long timestamp,
+ int tz, const char *msg, void *cb_data)
+{
+ printf("%s %s %s %lu %d %s\n",
+ sha1_to_hex(old_sha1), sha1_to_hex(new_sha1),
+ committer, timestamp, tz, msg);
+ return 0;
+}
+
+static int cmd_for_each_reflog_ent(struct ref_store *refs, const char **argv)
+{
+ const char *refname = notnull(*argv++, "refname");
+
+ return refs_for_each_reflog_ent(refs, refname, each_reflog, refs);
+}
+
+static int cmd_for_each_reflog_ent_reverse(struct ref_store *refs, const char **argv)
+{
+ const char *refname = notnull(*argv++, "refname");
+
+ return refs_for_each_reflog_ent_reverse(refs, refname, each_reflog, refs);
+}
+
+static int cmd_reflog_exists(struct ref_store *refs, const char **argv)
+{
+ const char *refname = notnull(*argv++, "refname");
+
+ return !refs_reflog_exists(refs, refname);
+}
+
+static int cmd_create_reflog(struct ref_store *refs, const char **argv)
+{
+ const char *refname = notnull(*argv++, "refname");
+ int force_create = arg_flags(*argv++, "force-create");
+ struct strbuf err = STRBUF_INIT;
+ int ret;
+
+ ret = refs_create_reflog(refs, refname, force_create, &err);
+ if (err.len)
+ puts(err.buf);
+ return ret;
+}
+
+static int cmd_delete_reflog(struct ref_store *refs, const char **argv)
+{
+ const char *refname = notnull(*argv++, "refname");
+
+ return refs_delete_reflog(refs, refname);
+}
+
+static int cmd_reflog_expire(struct ref_store *refs, const char **argv)
+{
+ die("not supported yet");
+}
+
+static int cmd_delete_ref(struct ref_store *refs, const char **argv)
+{
+ const char *refname = notnull(*argv++, "refname");
+ const char *sha1_buf = notnull(*argv++, "old-sha1");
+ unsigned int flags = arg_flags(*argv++, "flags");
+ unsigned char old_sha1[20];
+
+ if (get_sha1_hex(sha1_buf, old_sha1))
+ die("not sha-1");
+
+ return refs_delete_ref(refs, refname, old_sha1, flags);
+}
+
+static int cmd_update_ref(struct ref_store *refs, const char **argv)
+{
+ const char *msg = notnull(*argv++, "msg");
+ const char *refname = notnull(*argv++, "refname");
+ const char *new_sha1_buf = notnull(*argv++, "old-sha1");
+ const char *old_sha1_buf = notnull(*argv++, "old-sha1");
+ unsigned int flags = arg_flags(*argv++, "flags");
+ unsigned char old_sha1[20];
+ unsigned char new_sha1[20];
+
+ if (get_sha1_hex(old_sha1_buf, old_sha1) ||
+ get_sha1_hex(new_sha1_buf, new_sha1))
+ die("not sha-1");
+
+ return refs_update_ref(refs, msg, refname,
+ new_sha1, old_sha1,
+ flags, UPDATE_REFS_DIE_ON_ERR);
+}
+
+struct command {
+ const char *name;
+ int (*func)(struct ref_store *refs, const char **argv);
+};
+
+static struct command commands[] = {
+ { "pack-refs", cmd_pack_refs },
+ { "peel-ref", cmd_peel_ref },
+ { "create-symref", cmd_create_symref },
+ { "delete-refs", cmd_delete_refs },
+ { "rename-ref", cmd_rename_ref },
+ { "for-each-ref", cmd_for_each_ref },
+ { "resolve-ref", cmd_resolve_ref },
+ { "verify-ref", cmd_verify_ref },
+ { "for-each-reflog", cmd_for_each_reflog },
+ { "for-each-reflog-ent", cmd_for_each_reflog_ent },
+ { "for-each-reflog-ent-reverse", cmd_for_each_reflog_ent_reverse },
+ { "reflog-exists", cmd_reflog_exists },
+ { "create-reflog", cmd_create_reflog },
+ { "delete-reflog", cmd_delete_reflog },
+ { "reflog-expire", cmd_reflog_expire },
+ /*
+ * backend transaction functions can't be tested separately
+ */
+ { "delete-ref", cmd_delete_ref },
+ { "update-ref", cmd_update_ref },
+ { NULL, NULL }
+};
+
+int cmd_main(int argc, const char **argv)
+{
+ struct ref_store *refs;
+ const char *func;
+ struct command *cmd;
+
+ argv = get_store(argv + 1, &refs);
+
+ func = *argv++;
+ if (!func)
+ die("ref function required");
+ for (cmd = commands; cmd->name; cmd++) {
+ if (!strcmp(func, cmd->name))
+ return cmd->func(refs, argv);
+ }
+ die("unknown function %s", func);
+ return 0;
+}
--
2.11.0.157.gd943d85
^ permalink raw reply related
* [PATCH v5 23/24] t1405: some basic tests on main ref store
From: Nguyễn Thái Ngọc Duy @ 2017-02-22 14:04 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Michael Haggerty, Johannes Schindelin,
Ramsay Jones, Stefan Beller, novalis,
Nguyễn Thái Ngọc Duy
In-Reply-To: <20170222140450.30886-1-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
t/t1405-main-ref-store.sh (new +x) | 123 +++++++++++++++++++++++++++++++++++++
1 file changed, 123 insertions(+)
create mode 100755 t/t1405-main-ref-store.sh
diff --git a/t/t1405-main-ref-store.sh b/t/t1405-main-ref-store.sh
new file mode 100755
index 000000000..0999829f1
--- /dev/null
+++ b/t/t1405-main-ref-store.sh
@@ -0,0 +1,123 @@
+#!/bin/sh
+
+test_description='test main ref store api'
+
+. ./test-lib.sh
+
+RUN="test-ref-store main"
+
+test_expect_success 'pack_refs(PACK_REFS_ALL | PACK_REFS_PRUNE)' '
+ test_commit one &&
+ N=`find .git/refs -type f | wc -l` &&
+ test "$N" != 0 &&
+ $RUN pack-refs 3 &&
+ N=`find .git/refs -type f | wc -l`
+'
+
+test_expect_success 'peel_ref(new-tag)' '
+ git rev-parse HEAD >expected &&
+ git tag -a -m new-tag new-tag HEAD &&
+ $RUN peel-ref refs/tags/new-tag >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'create_symref(FOO, refs/heads/master)' '
+ $RUN create-symref FOO refs/heads/master nothing &&
+ echo refs/heads/master >expected &&
+ git symbolic-ref FOO >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'delete_refs(FOO, refs/tags/new-tag)' '
+ git rev-parse FOO -- &&
+ git rev-parse refs/tags/new-tag -- &&
+ $RUN delete-refs 0 FOO refs/tags/new-tag &&
+ test_must_fail git rev-parse FOO -- &&
+ test_must_fail git rev-parse refs/tags/new-tag --
+'
+
+test_expect_success 'rename_refs(master, new-master)' '
+ git rev-parse master >expected &&
+ $RUN rename-ref refs/heads/master refs/heads/new-master &&
+ git rev-parse new-master >actual &&
+ test_cmp expected actual &&
+ test_commit recreate-master
+'
+
+test_expect_success 'for_each_ref(refs/heads/)' '
+ $RUN for-each-ref refs/heads/ | cut -c 42- >actual &&
+ cat >expected <<-\EOF &&
+ master 0x0
+ new-master 0x0
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'resolve_ref(new-master)' '
+ SHA1=`git rev-parse new-master` &&
+ echo "$SHA1 refs/heads/new-master 0x0" >expected &&
+ $RUN resolve-ref refs/heads/new-master 0 >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'verify_ref(new-master)' '
+ $RUN verify-ref refs/heads/new-master
+'
+
+test_expect_success 'for_each_reflog()' '
+ $RUN for-each-reflog | cut -c 42- >actual &&
+ cat >expected <<-\EOF &&
+ refs/heads/master 0x0
+ refs/heads/new-master 0x0
+ HEAD 0x1
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'for_each_reflog_ent()' '
+ $RUN for-each-reflog-ent HEAD >actual &&
+ head -n1 actual | grep one &&
+ tail -n2 actual | head -n1 | grep recreate-master
+'
+
+test_expect_success 'for_each_reflog_ent_reverse()' '
+ $RUN for-each-reflog-ent-reverse HEAD >actual &&
+ head -n1 actual | grep recreate-master &&
+ tail -n2 actual | head -n1 | grep one
+'
+
+test_expect_success 'reflog_exists(HEAD)' '
+ $RUN reflog-exists HEAD
+'
+
+test_expect_success 'delete_reflog(HEAD)' '
+ $RUN delete-reflog HEAD &&
+ ! test -f .git/logs/HEAD
+'
+
+test_expect_success 'create-reflog(HEAD)' '
+ $RUN create-reflog HEAD 1 &&
+ test -f .git/logs/HEAD
+'
+
+test_expect_success 'delete_ref(refs/heads/foo)' '
+ git checkout -b foo &&
+ FOO_SHA1=`git rev-parse foo` &&
+ git checkout --detach &&
+ test_commit bar-commit &&
+ git checkout -b bar &&
+ BAR_SHA1=`git rev-parse bar` &&
+ $RUN update-ref updating refs/heads/foo $BAR_SHA1 $FOO_SHA1 0 &&
+ echo $BAR_SHA1 >expected &&
+ git rev-parse refs/heads/foo >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'delete_ref(refs/heads/foo)' '
+ SHA1=`git rev-parse foo` &&
+ git checkout --detach &&
+ $RUN delete-ref refs/heads/foo $SHA1 0 &&
+ test_must_fail git rev-parse refs/heads/foo --
+'
+
+test_done
--
2.11.0.157.gd943d85
^ permalink raw reply related
* [PATCH v5 24/24] t1406: new tests for submodule ref store
From: Nguyễn Thái Ngọc Duy @ 2017-02-22 14:04 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Michael Haggerty, Johannes Schindelin,
Ramsay Jones, Stefan Beller, novalis,
Nguyễn Thái Ngọc Duy
In-Reply-To: <20170222140450.30886-1-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
t/t1406-submodule-ref-store.sh (new +x) | 95 +++++++++++++++++++++++++++++++++
1 file changed, 95 insertions(+)
create mode 100755 t/t1406-submodule-ref-store.sh
diff --git a/t/t1406-submodule-ref-store.sh b/t/t1406-submodule-ref-store.sh
new file mode 100755
index 000000000..3b30ba62f
--- /dev/null
+++ b/t/t1406-submodule-ref-store.sh
@@ -0,0 +1,95 @@
+#!/bin/sh
+
+test_description='test submodule ref store api'
+
+. ./test-lib.sh
+
+RUN="test-ref-store submodule:sub"
+
+test_expect_success 'setup' '
+ git init sub &&
+ (
+ cd sub &&
+ test_commit first &&
+ git checkout -b new-master
+ )
+'
+
+test_expect_success 'pack_refs() not allowed' '
+ test_must_fail $RUN pack-refs 3
+'
+
+test_expect_success 'peel_ref(new-tag)' '
+ git -C sub rev-parse HEAD >expected &&
+ git -C sub tag -a -m new-tag new-tag HEAD &&
+ $RUN peel-ref refs/tags/new-tag >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'create_symref() not allowed' '
+ test_must_fail $RUN create-symref FOO refs/heads/master nothing
+'
+
+test_expect_success 'delete_refs() not allowed' '
+ test_must_fail $RUN delete-refs 0 FOO refs/tags/new-tag
+'
+
+test_expect_success 'rename_refs() not allowed' '
+ test_must_fail $RUN rename-ref refs/heads/master refs/heads/new-master
+'
+
+test_expect_success 'for_each_ref(refs/heads/)' '
+ $RUN for-each-ref refs/heads/ | cut -c 42- >actual &&
+ cat >expected <<-\EOF &&
+ master 0x0
+ new-master 0x0
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'resolve_ref(master)' '
+ SHA1=`git -C sub rev-parse master` &&
+ echo "$SHA1 refs/heads/master 0x0" >expected &&
+ $RUN resolve-ref refs/heads/master 0 >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'verify_ref(new-master)' '
+ $RUN verify-ref refs/heads/new-master
+'
+
+test_expect_success 'for_each_reflog()' '
+ $RUN for-each-reflog | cut -c 42- >actual &&
+ cat >expected <<-\EOF &&
+ refs/heads/master 0x0
+ refs/heads/new-master 0x0
+ HEAD 0x1
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'for_each_reflog_ent()' '
+ $RUN for-each-reflog-ent HEAD >actual && cat actual &&
+ head -n1 actual | grep first &&
+ tail -n2 actual | head -n1 | grep master.to.new
+'
+
+test_expect_success 'for_each_reflog_ent_reverse()' '
+ $RUN for-each-reflog-ent-reverse HEAD >actual &&
+ head -n1 actual | grep master.to.new &&
+ tail -n2 actual | head -n1 | grep first
+'
+
+test_expect_success 'reflog_exists(HEAD)' '
+ $RUN reflog-exists HEAD
+'
+
+test_expect_success 'delete_reflog() not allowed' '
+ test_must_fail $RUN delete-reflog HEAD
+'
+
+test_expect_success 'create-reflog() not allowed' '
+ test_must_fail $RUN create-reflog HEAD 1
+'
+
+test_done
--
2.11.0.157.gd943d85
^ permalink raw reply related
* Re: url.<base>.insteadOf vs. submodules
From: Jon Loeliger @ 2017-02-22 14:00 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Stefan Beller, Jeff King, Toolforger, git@vger.kernel.org
In-Reply-To: <xmqqbmtvdj7p.fsf@gitster.mtv.corp.google.com>
So, like, Junio C Hamano said:
> Stefan Beller <sbeller@google.com> writes:
>
> > Do we want to invent a special value for url.*.insteadOf to mean
> > "look up in superproject, so I don't have to keep
> > a copy that may get stale" ?
>
> My gut feeling is that we should do the selective/filtered include
> Peff mentioned when a repository is known to be used as a submodule
> of somebody else.
Does the management of these submodue-related config values
become easier if, instead of placing them in .config, we
place them in a git/.context file?
jdl
^ permalink raw reply
* Re: [PATCH] fetch: print an error when declining to request an unadvertised object
From: Matt McCutchen @ 2017-02-22 16:17 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <xmqqvas4gie9.fsf@gitster.mtv.corp.google.com>
On Mon, 2017-02-20 at 22:36 -0800, Junio C Hamano wrote:
> Hmph, I would have expected this to be done as a three-patch series,
>
> * move the loop at the end of cmd_fetch_pack() to a separate helper
> function report_unmatched_refs() and call it;
>
> * add a call to report_unmatched_refs() to the transport layer;
>
> * enhance report_unmatched_refs() by introducing match_status
> field and adding new code to filter_refs() to diagnose other
> kinds of errors.
Sure.
> The result looks reasonable from a cursory read, though.
>
> Thanks for following it up to the completion.
This remark led me to believe you were satisfied with the single patch,
but the last "What's cooking in git.git" mail says "Expecting a split
series?".
Anyway, I made a split series and will send it in a moment. I don't
know if all the commit messages include exactly the information you
want; hopefully you're happy to edit them as desired. Compared to the
previous patch, there is one fix in the net result: fixing t5500-fetch-
pack.sh to deal with the internationalized "no such remote ref"
message.
Matt
^ permalink raw reply
* [PATCH 2/3] fetch_refs_via_pack: call report_unmatched_refs
From: Matt McCutchen @ 2017-02-22 16:02 UTC (permalink / raw)
To: git
In-Reply-To: <xmqqvas4gie9.fsf@gitster.mtv.corp.google.com>
"git fetch" currently doesn't bother to check that it got all refs it
sought, because the common case of requesting a nonexistent ref triggers
a die() in get_fetch_map. However, there's at least one case that
slipped through: "git fetch REMOTE SHA1" if the server doesn't allow
requests for unadvertised objects. Make fetch_refs_via_pack (which is
on the "git fetch" code path) call report_unmatched_refs so that we at
least get an error message in that case.
---
t/t5516-fetch-push.sh | 3 ++-
transport.c | 14 +++++++++-----
2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 26b2caf..0d13a45 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -1098,7 +1098,8 @@ test_expect_success 'fetch exact SHA1' '
test_must_fail git cat-file -t $the_commit &&
# fetching the hidden object should fail by default
- test_must_fail git fetch -v ../testrepo $the_commit:refs/heads/copy &&
+ test_must_fail git fetch -v ../testrepo $the_commit:refs/heads/copy 2>err &&
+ test_i18ngrep "no such remote ref" err &&
test_must_fail git rev-parse --verify refs/heads/copy &&
# the server side can allow it to succeed
diff --git a/transport.c b/transport.c
index 04e5d66..c377907 100644
--- a/transport.c
+++ b/transport.c
@@ -204,6 +204,7 @@ static struct ref *get_refs_via_connect(struct transport *transport, int for_pus
static int fetch_refs_via_pack(struct transport *transport,
int nr_heads, struct ref **to_fetch)
{
+ int ret = 0;
struct git_transport_data *data = transport->data;
struct ref *refs;
char *dest = xstrdup(transport->url);
@@ -241,19 +242,22 @@ static int fetch_refs_via_pack(struct transport *transport,
&transport->pack_lockfile);
close(data->fd[0]);
close(data->fd[1]);
- if (finish_connect(data->conn)) {
- free_refs(refs);
- refs = NULL;
- }
+ if (finish_connect(data->conn))
+ ret = -1;
data->conn = NULL;
data->got_remote_heads = 0;
data->options.self_contained_and_connected =
args.self_contained_and_connected;
+ if (refs == NULL)
+ ret = -1;
+ if (report_unmatched_refs(to_fetch, nr_heads))
+ ret = -1;
+
free_refs(refs_tmp);
free_refs(refs);
free(dest);
- return (refs ? 0 : -1);
+ return ret;
}
static int push_had_errors(struct ref *ref)
--
2.9.3
^ permalink raw reply related
* [PATCH 1/3] fetch-pack: move code to report unmatched refs to a function
From: Matt McCutchen @ 2017-02-22 16:01 UTC (permalink / raw)
To: git
In-Reply-To: <xmqqvas4gie9.fsf@gitster.mtv.corp.google.com>
We're preparing to reuse this code in transport.c for "git fetch".
While I'm here, internationalize the existing error message.
---
builtin/fetch-pack.c | 7 +------
fetch-pack.c | 13 +++++++++++++
fetch-pack.h | 9 +++++++++
t/t5500-fetch-pack.sh | 6 +++---
4 files changed, 26 insertions(+), 9 deletions(-)
diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c
index cfe9e44..2a1c1c2 100644
--- a/builtin/fetch-pack.c
+++ b/builtin/fetch-pack.c
@@ -219,12 +219,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
* remote no-such-ref' would silently succeed without issuing
* an error.
*/
- for (i = 0; i < nr_sought; i++) {
- if (!sought[i] || sought[i]->matched)
- continue;
- error("no such remote ref %s", sought[i]->name);
- ret = 1;
- }
+ ret |= report_unmatched_refs(sought, nr_sought);
while (ref) {
printf("%s %s\n",
diff --git a/fetch-pack.c b/fetch-pack.c
index 601f077..7c8d44c 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -1094,3 +1094,16 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
clear_shallow_info(&si);
return ref_cpy;
}
+
+int report_unmatched_refs(struct ref **sought, int nr_sought)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < nr_sought; i++) {
+ if (!sought[i] || sought[i]->matched)
+ continue;
+ error(_("no such remote ref %s"), sought[i]->name);
+ ret = 1;
+ }
+ return ret;
+}
diff --git a/fetch-pack.h b/fetch-pack.h
index c912e3d..fd4d80e 100644
--- a/fetch-pack.h
+++ b/fetch-pack.h
@@ -45,4 +45,13 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
struct sha1_array *shallow,
char **pack_lockfile);
+/*
+ * Print an appropriate error message for each sought ref that wasn't
+ * matched. Return 0 if all sought refs were matched, otherwise 1.
+ *
+ * The type of "sought" should be "const struct ref *const *" but for
+ * http://stackoverflow.com/questions/5055655/double-pointer-const-correctness-warnings-in-c .
+ */
+int report_unmatched_refs(struct ref **sought, int nr_sought);
+
#endif
diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh
index 505e1b4..b5865b3 100755
--- a/t/t5500-fetch-pack.sh
+++ b/t/t5500-fetch-pack.sh
@@ -484,7 +484,7 @@ test_expect_success 'test lonely missing ref' '
cd client &&
test_must_fail git fetch-pack --no-progress .. refs/heads/xyzzy
) >/dev/null 2>error-m &&
- test_cmp expect-error error-m
+ test_i18ncmp expect-error error-m
'
test_expect_success 'test missing ref after existing' '
@@ -492,7 +492,7 @@ test_expect_success 'test missing ref after existing' '
cd client &&
test_must_fail git fetch-pack --no-progress .. refs/heads/A refs/heads/xyzzy
) >/dev/null 2>error-em &&
- test_cmp expect-error error-em
+ test_i18ncmp expect-error error-em
'
test_expect_success 'test missing ref before existing' '
@@ -500,7 +500,7 @@ test_expect_success 'test missing ref before existing' '
cd client &&
test_must_fail git fetch-pack --no-progress .. refs/heads/xyzzy refs/heads/A
) >/dev/null 2>error-me &&
- test_cmp expect-error error-me
+ test_i18ncmp expect-error error-me
'
test_expect_success 'test --all, --depth, and explicit head' '
--
2.9.3
^ permalink raw reply related
* [PATCH 3/3] fetch-pack: add specific error for fetching an unadvertised object
From: Matt McCutchen @ 2017-02-22 16:05 UTC (permalink / raw)
To: git
In-Reply-To: <xmqqvas4gie9.fsf@gitster.mtv.corp.google.com>
Enhance filter_refs (which decides whether a request for an unadvertised
object should be sent to the server) to record a new match status on the
"struct ref" when a request is not allowed, and have
report_unmatched_refs check for this status and print a special error
message, "Server does not allow request for unadvertised object".
---
fetch-pack.c | 42 +++++++++++++++++++++++++++---------------
remote.h | 9 +++++++--
t/t5516-fetch-push.sh | 2 +-
3 files changed, 35 insertions(+), 18 deletions(-)
diff --git a/fetch-pack.c b/fetch-pack.c
index 7c8d44c..f12bfcd 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -578,7 +578,7 @@ static void filter_refs(struct fetch_pack_args *args,
break; /* definitely do not have it */
else if (cmp == 0) {
keep = 1; /* definitely have it */
- sought[i]->matched = 1;
+ sought[i]->match_status = REF_MATCHED;
}
i++;
}
@@ -598,22 +598,24 @@ static void filter_refs(struct fetch_pack_args *args,
}
/* Append unmatched requests to the list */
- if ((allow_unadvertised_object_request &
- (ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1))) {
- for (i = 0; i < nr_sought; i++) {
- unsigned char sha1[20];
+ for (i = 0; i < nr_sought; i++) {
+ unsigned char sha1[20];
- ref = sought[i];
- if (ref->matched)
- continue;
- if (get_sha1_hex(ref->name, sha1) ||
- ref->name[40] != '\0' ||
- hashcmp(sha1, ref->old_oid.hash))
- continue;
+ ref = sought[i];
+ if (ref->match_status != REF_NOT_MATCHED)
+ continue;
+ if (get_sha1_hex(ref->name, sha1) ||
+ ref->name[40] != '\0' ||
+ hashcmp(sha1, ref->old_oid.hash))
+ continue;
- ref->matched = 1;
+ if ((allow_unadvertised_object_request &
+ (ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1))) {
+ ref->match_status = REF_MATCHED;
*newtail = copy_ref(ref);
newtail = &(*newtail)->next;
+ } else {
+ ref->match_status = REF_UNADVERTISED_NOT_ALLOWED;
}
}
*refs = newlist;
@@ -1100,9 +1102,19 @@ int report_unmatched_refs(struct ref **sought, int nr_sought)
int i, ret = 0;
for (i = 0; i < nr_sought; i++) {
- if (!sought[i] || sought[i]->matched)
+ if (!sought[i])
continue;
- error(_("no such remote ref %s"), sought[i]->name);
+ switch (sought[i]->match_status) {
+ case REF_MATCHED:
+ continue;
+ case REF_NOT_MATCHED:
+ error(_("no such remote ref %s"), sought[i]->name);
+ break;
+ case REF_UNADVERTISED_NOT_ALLOWED:
+ error(_("Server does not allow request for unadvertised object %s"),
+ sought[i]->name);
+ break;
+ }
ret = 1;
}
return ret;
diff --git a/remote.h b/remote.h
index 9248811..0b9d8c4 100644
--- a/remote.h
+++ b/remote.h
@@ -89,8 +89,13 @@ struct ref {
force:1,
forced_update:1,
expect_old_sha1:1,
- deletion:1,
- matched:1;
+ deletion:1;
+
+ enum {
+ REF_NOT_MATCHED = 0, /* initial value */
+ REF_MATCHED,
+ REF_UNADVERTISED_NOT_ALLOWED
+ } match_status;
/*
* Order is important here, as we write to FETCH_HEAD
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 0d13a45..78f3b8e 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -1099,7 +1099,7 @@ test_expect_success 'fetch exact SHA1' '
# fetching the hidden object should fail by default
test_must_fail git fetch -v ../testrepo $the_commit:refs/heads/copy 2>err &&
- test_i18ngrep "no such remote ref" err &&
+ test_i18ngrep "Server does not allow request for unadvertised object" err &&
test_must_fail git rev-parse --verify refs/heads/copy &&
# the server side can allow it to succeed
--
2.9.3
^ permalink raw reply related
* Re: [PATCH] fetch: print an error when declining to request an unadvertised object
From: Junio C Hamano @ 2017-02-22 17:07 UTC (permalink / raw)
To: Matt McCutchen; +Cc: git
In-Reply-To: <1487780254.3016.1.camel@mattmccutchen.net>
Matt McCutchen <matt@mattmccutchen.net> writes:
> Anyway, I made a split series and will send it in a moment. I don't
> know if all the commit messages include exactly the information you
> want; hopefully you're happy to edit them as desired. Compared to the
> previous patch, there is one fix in the net result: fixing t5500-fetch-
> pack.sh to deal with the internationalized "no such remote ref"
> message.
Thanks for going an extra mile. I think many developers in the
future who reads "git log" will thank you, too. The changes,
especially the one in the last one, are very much more
understandable compared to the original, even if the end result is
the same.
^ permalink raw reply
* Re: [PATCH 1/3] fetch-pack: move code to report unmatched refs to a function
From: Junio C Hamano @ 2017-02-22 17:11 UTC (permalink / raw)
To: Matt McCutchen; +Cc: git
In-Reply-To: <b9b52233e84a7f5bd0526f9625e4be06cbbd0ace.1487779910.git.matt@mattmccutchen.net>
Matt McCutchen <matt@mattmccutchen.net> writes:
> We're preparing to reuse this code in transport.c for "git fetch".
>
> While I'm here, internationalize the existing error message.
> ---
Sounds good. Please just say it is OK for me to forge your sign-off ;-)
> diff --git a/fetch-pack.h b/fetch-pack.h
> index c912e3d..fd4d80e 100644
> --- a/fetch-pack.h
> +++ b/fetch-pack.h
> @@ -45,4 +45,13 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
> struct sha1_array *shallow,
> char **pack_lockfile);
>
> +/*
> + * Print an appropriate error message for each sought ref that wasn't
> + * matched. Return 0 if all sought refs were matched, otherwise 1.
> + *
> + * The type of "sought" should be "const struct ref *const *" but for
> + * http://stackoverflow.com/questions/5055655/double-pointer-const-correctness-warnings-in-c .
> + */
This is an unfinished sentence, but I wonder if we even need to have
it here? I'd be surprised if this function was unique in the
codebase that takes an array pointer whose type is looser than
necessary because of well-known language rules.
^ permalink raw reply
* Re: `git show --oneline commit` does not do what's intuitively expected
From: Linus Torvalds @ 2017-02-22 17:18 UTC (permalink / raw)
To: Jeff King; +Cc: Luna Kid, git
In-Reply-To: <20170217040522.jugt4uuak74l3qjw@sigill.intra.peff.net>
On Thu, Feb 16, 2017 at 8:05 PM, Jeff King <peff@peff.net> wrote:
> On Fri, Feb 17, 2017 at 02:51:36AM +0100, Luna Kid wrote:
>
>> tl;dr; --> Please add --no-diff (or --msg-only) to git show. We'll
>> love you for that. :)
>
> I think it is already spelled "--no-patch", or "-s" for short.
I think people should also learn about "--no-walk" (or the numberic
walk limiters) to the revision walking logic, because it can often be
useful.
IOW, if you only want the commit info, you can certainly use "git show
-s", but you can also use
git log --no-walk .. list of commits ..
or
git log -1 <single-commit>
to show a commit without any other details.
Basically, "git show" for a commit does what is mostly equivalent to
git log --cc --no-walk
although "git show" then has other features too (ie it shows non-commits etc).
Linus
^ permalink raw reply
* Re: [RFC][Git GUI] Make Commit message field in git GUI re sizable.
From: Marc Branchaud @ 2017-02-22 17:15 UTC (permalink / raw)
To: Jessie Hernandez, Bert Wesarg; +Cc: Git Mailing List, Pat Thoyts
In-Reply-To: <dfcc54b406d9f46cf358b7ead128bf65.squirrel@mail.jessiehernandez.com>
On 2017-02-22 06:59 AM, Jessie Hernandez wrote:
>> HI,
>>
>> the reason why it is fixed, is because commit messages should be
>> wrapped at 76 characters to be used in mails. So it helps you with the
>> wrapping.
>>
>> Bert
>
> Right ok. I understand.
> Knowing this I think I might start writing my commit messages differently
> then.
You can configure gui.commitMsgWidth if you don't like the default
(which is 75, not 76).
M.
> Thank you for this.
>
> Regards
>
> -----------------
> Jessie Hernandez
>
>>
>>
>> On Wed, Feb 22, 2017 at 10:27 AM, Jessie Hernandez
>> <jessie@jessiehernandez.com> wrote:
>>> Hi all,
>>>
>>> I have been using git for a few years now and really like the software.
>>> I have a small annoyance and was wondering if I could get the
>>> communities
>>> view on this.
>>>
>>> When using git GUI I find it handy to be able to re-size the "Unstaged
>>> Changes" and the "Staged Changed" fields.
>>>
>>> I would like the same thing for the "Commit Message" field, or to have
>>> it
>>> re-size with the git GUI window.
>>>
>>> I can re-size the "Commit Message" vertically when making the "Modified"
>>> panel smaller.
>>>
>>> Does this make sense?
>>> I would be happy to get into more detail if that is necessary or if
>>> something is not clear.
>>>
>>> Thank you.
>>>
>>> -----------------
>>> Jessie Hernandez
>>>
>>>
>>
>
>
^ permalink raw reply
* Re: [PATCH v5 00/24] Remove submodule from files-backend.c
From: Junio C Hamano @ 2017-02-22 17:18 UTC (permalink / raw)
To: Nguyễn Thái Ngọc Duy
Cc: git, Michael Haggerty, Johannes Schindelin, Ramsay Jones,
Stefan Beller, novalis
In-Reply-To: <20170222140450.30886-1-pclouds@gmail.com>
Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes:
> v5 goes a bit longer than v4, basically:
>
> - files_path() is broken down into three smaller functions,
> files_{packed_refs,reflog,refname}_path().
>
> - most of store-based api is added because..
>
> - test-ref-store.c is added with t1405 and t1406 for some basic tests
> I'm not aimimg for complete ref store coverage. But we can continue
> to improve from there.
>
> - refs_store_init() now takes a "permission" flag, like open().
> Operations are allowed or forbidden based on this flag. The
> submodule_allowed flag is killed. files_assert_main.. remains.
>
> - get_*_ref_store() remain public api because it's used by
> test-ref-store.c and pack-refs.c.
>
> - files-backend.c should now make no function calls that implicitly
> target the main store. But this will have to be tested more to be
> sure. I'm tempted to add a tracing backend just for this purpose.
OK.
> Junio, if you take this on 'pu', you'll have to kick my other two
> series out (they should not even compile). I'm not resending them
> until I get a "looks mostly ok" from Michael. No point in updating
> them when this series keeps moving.
Thanks for a note.
^ permalink raw reply
* [PATCH v2 1/3] fetch-pack: move code to report unmatched refs to a function
From: Matt McCutchen @ 2017-02-22 16:01 UTC (permalink / raw)
To: git
In-Reply-To: <xmqqpoiacfqw.fsf@gitster.mtv.corp.google.com>
We're preparing to reuse this code in transport.c for "git fetch".
While I'm here, internationalize the existing error message.
Signed-off-by: Matt McCutchen <matt@mattmccutchen.net>
---
builtin/fetch-pack.c | 7 +------
fetch-pack.c | 13 +++++++++++++
fetch-pack.h | 6 ++++++
t/t5500-fetch-pack.sh | 6 +++---
4 files changed, 23 insertions(+), 9 deletions(-)
diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c
index cfe9e44..2a1c1c2 100644
--- a/builtin/fetch-pack.c
+++ b/builtin/fetch-pack.c
@@ -219,12 +219,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
* remote no-such-ref' would silently succeed without issuing
* an error.
*/
- for (i = 0; i < nr_sought; i++) {
- if (!sought[i] || sought[i]->matched)
- continue;
- error("no such remote ref %s", sought[i]->name);
- ret = 1;
- }
+ ret |= report_unmatched_refs(sought, nr_sought);
while (ref) {
printf("%s %s\n",
diff --git a/fetch-pack.c b/fetch-pack.c
index 601f077..7c8d44c 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -1094,3 +1094,16 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
clear_shallow_info(&si);
return ref_cpy;
}
+
+int report_unmatched_refs(struct ref **sought, int nr_sought)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < nr_sought; i++) {
+ if (!sought[i] || sought[i]->matched)
+ continue;
+ error(_("no such remote ref %s"), sought[i]->name);
+ ret = 1;
+ }
+ return ret;
+}
diff --git a/fetch-pack.h b/fetch-pack.h
index c912e3d..a2d46e6 100644
--- a/fetch-pack.h
+++ b/fetch-pack.h
@@ -45,4 +45,10 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
struct sha1_array *shallow,
char **pack_lockfile);
+/*
+ * Print an appropriate error message for each sought ref that wasn't
+ * matched. Return 0 if all sought refs were matched, otherwise 1.
+ */
+int report_unmatched_refs(struct ref **sought, int nr_sought);
+
#endif
diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh
index 505e1b4..b5865b3 100755
--- a/t/t5500-fetch-pack.sh
+++ b/t/t5500-fetch-pack.sh
@@ -484,7 +484,7 @@ test_expect_success 'test lonely missing ref' '
cd client &&
test_must_fail git fetch-pack --no-progress .. refs/heads/xyzzy
) >/dev/null 2>error-m &&
- test_cmp expect-error error-m
+ test_i18ncmp expect-error error-m
'
test_expect_success 'test missing ref after existing' '
@@ -492,7 +492,7 @@ test_expect_success 'test missing ref after existing' '
cd client &&
test_must_fail git fetch-pack --no-progress .. refs/heads/A refs/heads/xyzzy
) >/dev/null 2>error-em &&
- test_cmp expect-error error-em
+ test_i18ncmp expect-error error-em
'
test_expect_success 'test missing ref before existing' '
@@ -500,7 +500,7 @@ test_expect_success 'test missing ref before existing' '
cd client &&
test_must_fail git fetch-pack --no-progress .. refs/heads/xyzzy refs/heads/A
) >/dev/null 2>error-me &&
- test_cmp expect-error error-me
+ test_i18ncmp expect-error error-me
'
test_expect_success 'test --all, --depth, and explicit head' '
--
2.9.3
^ permalink raw reply related
* [PATCH v2 3/3] fetch-pack: add specific error for fetching an unadvertised object
From: Matt McCutchen @ 2017-02-22 16:05 UTC (permalink / raw)
To: git
In-Reply-To: <xmqqpoiacfqw.fsf@gitster.mtv.corp.google.com>
Enhance filter_refs (which decides whether a request for an unadvertised
object should be sent to the server) to record a new match status on the
"struct ref" when a request is not allowed, and have
report_unmatched_refs check for this status and print a special error
message, "Server does not allow request for unadvertised object".
Signed-off-by: Matt McCutchen <matt@mattmccutchen.net>
---
fetch-pack.c | 42 +++++++++++++++++++++++++++---------------
remote.h | 9 +++++++--
t/t5516-fetch-push.sh | 2 +-
3 files changed, 35 insertions(+), 18 deletions(-)
diff --git a/fetch-pack.c b/fetch-pack.c
index 7c8d44c..f12bfcd 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -578,7 +578,7 @@ static void filter_refs(struct fetch_pack_args *args,
break; /* definitely do not have it */
else if (cmp == 0) {
keep = 1; /* definitely have it */
- sought[i]->matched = 1;
+ sought[i]->match_status = REF_MATCHED;
}
i++;
}
@@ -598,22 +598,24 @@ static void filter_refs(struct fetch_pack_args *args,
}
/* Append unmatched requests to the list */
- if ((allow_unadvertised_object_request &
- (ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1))) {
- for (i = 0; i < nr_sought; i++) {
- unsigned char sha1[20];
+ for (i = 0; i < nr_sought; i++) {
+ unsigned char sha1[20];
- ref = sought[i];
- if (ref->matched)
- continue;
- if (get_sha1_hex(ref->name, sha1) ||
- ref->name[40] != '\0' ||
- hashcmp(sha1, ref->old_oid.hash))
- continue;
+ ref = sought[i];
+ if (ref->match_status != REF_NOT_MATCHED)
+ continue;
+ if (get_sha1_hex(ref->name, sha1) ||
+ ref->name[40] != '\0' ||
+ hashcmp(sha1, ref->old_oid.hash))
+ continue;
- ref->matched = 1;
+ if ((allow_unadvertised_object_request &
+ (ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1))) {
+ ref->match_status = REF_MATCHED;
*newtail = copy_ref(ref);
newtail = &(*newtail)->next;
+ } else {
+ ref->match_status = REF_UNADVERTISED_NOT_ALLOWED;
}
}
*refs = newlist;
@@ -1100,9 +1102,19 @@ int report_unmatched_refs(struct ref **sought, int nr_sought)
int i, ret = 0;
for (i = 0; i < nr_sought; i++) {
- if (!sought[i] || sought[i]->matched)
+ if (!sought[i])
continue;
- error(_("no such remote ref %s"), sought[i]->name);
+ switch (sought[i]->match_status) {
+ case REF_MATCHED:
+ continue;
+ case REF_NOT_MATCHED:
+ error(_("no such remote ref %s"), sought[i]->name);
+ break;
+ case REF_UNADVERTISED_NOT_ALLOWED:
+ error(_("Server does not allow request for unadvertised object %s"),
+ sought[i]->name);
+ break;
+ }
ret = 1;
}
return ret;
diff --git a/remote.h b/remote.h
index 9248811..0b9d8c4 100644
--- a/remote.h
+++ b/remote.h
@@ -89,8 +89,13 @@ struct ref {
force:1,
forced_update:1,
expect_old_sha1:1,
- deletion:1,
- matched:1;
+ deletion:1;
+
+ enum {
+ REF_NOT_MATCHED = 0, /* initial value */
+ REF_MATCHED,
+ REF_UNADVERTISED_NOT_ALLOWED
+ } match_status;
/*
* Order is important here, as we write to FETCH_HEAD
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 0d13a45..78f3b8e 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -1099,7 +1099,7 @@ test_expect_success 'fetch exact SHA1' '
# fetching the hidden object should fail by default
test_must_fail git fetch -v ../testrepo $the_commit:refs/heads/copy 2>err &&
- test_i18ngrep "no such remote ref" err &&
+ test_i18ngrep "Server does not allow request for unadvertised object" err &&
test_must_fail git rev-parse --verify refs/heads/copy &&
# the server side can allow it to succeed
--
2.9.3
^ permalink raw reply related
* [PATCH v2 2/3] fetch_refs_via_pack: call report_unmatched_refs
From: Matt McCutchen @ 2017-02-22 16:02 UTC (permalink / raw)
To: git
In-Reply-To: <xmqqpoiacfqw.fsf@gitster.mtv.corp.google.com>
"git fetch" currently doesn't bother to check that it got all refs it
sought, because the common case of requesting a nonexistent ref triggers
a die() in get_fetch_map. However, there's at least one case that
slipped through: "git fetch REMOTE SHA1" if the server doesn't allow
requests for unadvertised objects. Make fetch_refs_via_pack (which is
on the "git fetch" code path) call report_unmatched_refs so that we at
least get an error message in that case.
Signed-off-by: Matt McCutchen <matt@mattmccutchen.net>
---
t/t5516-fetch-push.sh | 3 ++-
transport.c | 14 +++++++++-----
2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 26b2caf..0d13a45 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -1098,7 +1098,8 @@ test_expect_success 'fetch exact SHA1' '
test_must_fail git cat-file -t $the_commit &&
# fetching the hidden object should fail by default
- test_must_fail git fetch -v ../testrepo $the_commit:refs/heads/copy &&
+ test_must_fail git fetch -v ../testrepo $the_commit:refs/heads/copy 2>err &&
+ test_i18ngrep "no such remote ref" err &&
test_must_fail git rev-parse --verify refs/heads/copy &&
# the server side can allow it to succeed
diff --git a/transport.c b/transport.c
index 04e5d66..c377907 100644
--- a/transport.c
+++ b/transport.c
@@ -204,6 +204,7 @@ static struct ref *get_refs_via_connect(struct transport *transport, int for_pus
static int fetch_refs_via_pack(struct transport *transport,
int nr_heads, struct ref **to_fetch)
{
+ int ret = 0;
struct git_transport_data *data = transport->data;
struct ref *refs;
char *dest = xstrdup(transport->url);
@@ -241,19 +242,22 @@ static int fetch_refs_via_pack(struct transport *transport,
&transport->pack_lockfile);
close(data->fd[0]);
close(data->fd[1]);
- if (finish_connect(data->conn)) {
- free_refs(refs);
- refs = NULL;
- }
+ if (finish_connect(data->conn))
+ ret = -1;
data->conn = NULL;
data->got_remote_heads = 0;
data->options.self_contained_and_connected =
args.self_contained_and_connected;
+ if (refs == NULL)
+ ret = -1;
+ if (report_unmatched_refs(to_fetch, nr_heads))
+ ret = -1;
+
free_refs(refs_tmp);
free_refs(refs);
free(dest);
- return (refs ? 0 : -1);
+ return ret;
}
static int push_had_errors(struct ref *ref)
--
2.9.3
^ permalink raw reply related
* Re: [PATCH 1/3] fetch-pack: move code to report unmatched refs to a function
From: Matt McCutchen @ 2017-02-22 17:26 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <xmqqpoiacfqw.fsf@gitster.mtv.corp.google.com>
On Wed, 2017-02-22 at 09:11 -0800, Junio C Hamano wrote:
> Matt McCutchen <matt@mattmccutchen.net> writes:
>
> > We're preparing to reuse this code in transport.c for "git fetch".
> >
> > While I'm here, internationalize the existing error message.
> > ---
>
> Sounds good. Please just say it is OK for me to forge your sign-off
> ;-)
Oops. Given the other issue below, I'll just regenerate the patch
series.
> > diff --git a/fetch-pack.h b/fetch-pack.h
> > index c912e3d..fd4d80e 100644
> > --- a/fetch-pack.h
> > +++ b/fetch-pack.h
> > @@ -45,4 +45,13 @@ struct ref *fetch_pack(struct fetch_pack_args
> > *args,
> > struct sha1_array *shallow,
> > char **pack_lockfile);
> >
> > +/*
> > + * Print an appropriate error message for each sought ref that
> > wasn't
> > + * matched. Return 0 if all sought refs were matched, otherwise
> > 1.
> > + *
> > + * The type of "sought" should be "const struct ref *const *" but
> > for
> > + * http://stackoverflow.com/questions/5055655/double-pointer-const
> > -correctness-warnings-in-c .
> > + */
>
> This is an unfinished sentence, but I wonder if we even need to have
> it here? I'd be surprised if this function was unique in the
> codebase that takes an array pointer whose type is looser than
> necessary because of well-known language rules.
You're probably right. I'm in the habit of documenting things that
were unknown to me, but I'll take your word for what's well-known to
the average git developer. I'll remove the remark.
Matt
^ permalink raw reply
* [PATCH] http(s): automatically try NTLM authentication first
From: David Turner @ 2017-02-22 17:39 UTC (permalink / raw)
To: git; +Cc: sandals, Johannes Schindelin, David Turner
From: Johannes Schindelin <johannes.schindelin@gmx.de>
It is common in corporate setups to have permissions managed via a
domain account. That means that the user does not really have to log in
when accessing a central repository via https://, but that the login
credentials are used to authenticate with that repository.
The common way to do that used to require empty credentials, i.e. hitting
Enter twice when being asked for user name and password, or by using the
very funny notation https://:@server/repository
A recent commit (5275c3081c (http: http.emptyauth should allow empty (not
just NULL) usernames, 2016-10-04)) broke that usage, though, all of a
sudden requiring users to set http.emptyAuth = true.
Which brings us to the bigger question why http.emptyAuth defaults to
false, to begin with.
It would be one thing if cURL would not let the user specify credentials
interactively after attempting NTLM authentication (i.e. login
credentials), but that is not the case.
It would be another thing if attempting NTLM authentication was not
usually what users need to do when trying to authenticate via https://.
But that is also not the case.
So let's just go ahead and change the default, and unbreak the NTLM
authentication. As a bonus, this also makes the "you need to hit Enter
twice" (which is hard to explain: why enter empty credentials when you
want to authenticate with your login credentials?) and the ":@" hack
(which is also pretty, pretty hard to explain to users) obsolete.
This fixes https://github.com/git-for-windows/git/issues/987
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: David Turner <dturner@twosigma.com>
---
This has been in git for Windows for a few months (without the
config.txt change). We've also been using it internally. So I think
it's time to merge back to upstream git.
Documentation/config.txt | 3 ++-
http.c | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index fc5a28a320..b0da64ed33 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -1742,7 +1742,8 @@ http.emptyAuth::
Attempt authentication without seeking a username or password. This
can be used to attempt GSS-Negotiate authentication without specifying
a username in the URL, as libcurl normally requires a username for
- authentication.
+ authentication. Default is true, since if this fails, git will fall
+ back to asking the user for their username/password.
http.delegation::
Control GSSAPI credential delegation. The delegation is disabled
diff --git a/http.c b/http.c
index 90a1c0f113..943e630ea6 100644
--- a/http.c
+++ b/http.c
@@ -109,7 +109,7 @@ static int curl_save_cookies;
struct credential http_auth = CREDENTIAL_INIT;
static int http_proactive_auth;
static const char *user_agent;
-static int curl_empty_auth;
+static int curl_empty_auth = 1;
enum http_follow_config http_follow_config = HTTP_FOLLOW_INITIAL;
--
2.11.GIT
^ permalink raw reply related
* Re: [PATCH] Documentation: Link git-ls-files to core.quotePath variable.
From: Junio C Hamano @ 2017-02-22 17:41 UTC (permalink / raw)
To: Andreas Heiduk; +Cc: git
In-Reply-To: <e55b3cb7-65bf-1609-2e8d-823b4336e07a@gmail.com>
Andreas Heiduk <asheiduk@gmail.com> writes:
> [PATCH] Documentation: Clarify core.quotePath, remove cruft in
> git-ls-files.
>
> Signed-off-by: Andreas Heiduk <asheiduk@gmail.com>
> ---
>
> I have merged the best parts about quoting into the core.quotePath
> description and cleaned up the text in git-ls-files.txt regarding the
> control characters.
>
>
> Documentation/config.txt | 22 ++++++++++++----------
> Documentation/git-ls-files.txt | 11 ++++++-----
> 2 files changed, 18 insertions(+), 15 deletions(-)
>
> diff --git a/Documentation/config.txt b/Documentation/config.txt
> index f4721a0..25e65ae 100644
> --- a/Documentation/config.txt
> +++ b/Documentation/config.txt
> @@ -340,16 +340,18 @@ core.checkStat::
> all fields, including the sub-second part of mtime and ctime.
>
> core.quotePath::
> - The commands that output paths (e.g. 'ls-files',
> - 'diff'), when not given the `-z` option, will quote
> - "unusual" characters in the pathname by enclosing the
> - pathname in a double-quote pair and with backslashes the
> - same way strings in C source code are quoted. If this
> - variable is set to false, the bytes higher than 0x80 are
> - not quoted but output as verbatim. Note that double
> - quote, backslash and control characters are always
> - quoted without `-z` regardless of the setting of this
> - variable.
> + Commands that output paths (e.g. 'ls-files', 'diff'), will
> + quote "unusual" characters in the pathname by enclosing the
> + pathname in double-quotes and escaping those characters with
> + backslashes in the same way C escapes control characters (e.g.
> + `\t` for TAB, `\n` for LF, `\\` for backslash) or bytes with
> + values larger than 0x80 (e.g. octal `\265` for "micro"). If
> + this variable is set to false, bytes higher than 0x80 are not
> + considered "unusual" any more. Double-quotes, backslash and
> + control characters are always escaped regardless of the
> + setting of this variable. Many commands can output pathnames
> + completely verbatim using the `-z` option. The default value is
> + true.
Even though I am not sure "\265 is micro" is a good example these
days, as "high-bit set" is primarily meant to catch UTF-8
multi-bytes, I find the above much easier to read than the original.
> diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt
> index d2b17f2..88df561 100644
> --- a/Documentation/git-ls-files.txt
> +++ b/Documentation/git-ls-files.txt
> @@ -76,7 +76,8 @@ OPTIONS
> succeed.
>
> -z::
> - \0 line termination on output.
> + \0 line termination on output and do not quote filenames.
> + See OUTPUT below for more information.
>
> -x <pattern>::
> --exclude=<pattern>::
> @@ -192,10 +193,10 @@ the index records up to three such pairs; one from
> tree O in stage
> the user (or the porcelain) to see what should eventually be recorded
> at the
> path. (see linkgit:git-read-tree[1] for more information on state)
>
> -When `-z` option is not used, TAB, LF, and backslash characters
> -in pathnames are represented as `\t`, `\n`, and `\\`,
> -respectively. The path is also quoted according to the
> -configuration variable `core.quotePath` (see linkgit:git-config[1]).
> +Without the `-z` option pathnamens with "unusual" characters are
> +quoted as explained for the configuration variable `core.quotePath`
> +(see linkgit:git-config[1]). Using `-z` the filename is output
> +verbatim and the line is terminated by a NUL byte.
Yup, this looks much nicer than the original.
Thanks.
^ permalink raw reply
* Re: url.<base>.insteadOf vs. submodules
From: Junio C Hamano @ 2017-02-22 17:36 UTC (permalink / raw)
To: Jon Loeliger; +Cc: Stefan Beller, Jeff King, Toolforger, git@vger.kernel.org
In-Reply-To: <E1cgXSe-0007jp-QI@mylo.jdl.com>
Jon Loeliger <jdl@jdl.com> writes:
> So, like, Junio C Hamano said:
>> Stefan Beller <sbeller@google.com> writes:
>>
>> > Do we want to invent a special value for url.*.insteadOf to mean
>> > "look up in superproject, so I don't have to keep
>> > a copy that may get stale" ?
>>
>> My gut feeling is that we should do the selective/filtered include
>> Peff mentioned when a repository is known to be used as a submodule
>> of somebody else.
>
> Does the management of these submodue-related config values
> become easier if, instead of placing them in .config, we
> place them in a git/.context file?
Do you mean that Git users that use submodules adopt a convention
where a separate file in $GIT_DIR of the toplevel superproject holds
pieces of configuration that are meant to be shared between the
superproject and across all its submodules, and the $GIT_DIR/config
file in submodules and the superproject all include that shared one
via include.path mechanism?
That may allow us to do without being responsible for sifting of
configuration variables into safe and unsafe bins.
I dunno.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox