{"thread":{"id":"37379","subject":"[PATCH v3 00/23] backend-struct-db","startedAt":"2014-08-19T16:30:24Z","lastAt":"2014-08-26T22:34:19Z","messageCount":27,"participants":["Ronnie Sahlberg","Junio C Hamano"],"isPatch":true,"patchVersion":3,"patchTotal":23},"messages":[{"id":"247925","messageId":"1408465847-30384-1-git-send-email-sahlberg@google.com","threadId":"37379","inReplyTo":null,"subject":"[PATCH v3 00/23] backend-struct-db","fromName":"Ronnie Sahlberg","fromEmail":"sahlberg@google.com","sentAt":"2014-08-19T16:30:24Z","receivedAt":"2014-08-19T16:30:24Z","isPatch":true,"sender":{"key":"sahlberg@google.com","avatar":"https://avatars.githubusercontent.com/u/7320636?v=4"},"body":"List, please review\n\nThis series is called backend-struct-db and is also available at\nhttps://github.com/rsahlberg/git/tree/backend-struct-db\n\nThis series is built on and follows after the series\nref-transactions-send-pack\n\n\nThis series does not change any logic or behaviour but mainly just shuffles\ncode around and adds method pointers for the backend functions.\n\nThe first patch adds a new public function for checking if a refname is\navailable or not. This function is needed not because we want to have\ndifferent is_refname_available semantics for different backends, we don't,\nbut because its implementation is quite dependant on the backend type.\n\n15 of the patches, the refs-common.c patches, focuses on moving all backend\nagnostic refs functions to a common file. This file will contain all\nbackend agnostic refs functions.\n\nThe last 6 patches adds a backend structure with the methods we need to\ndescribe a pluggable backend. Currently we only have one built in backend,\nthe current files based backend. These patches do not change any of the\nbehavior other than that we now call the methods through backend specific\nwrapper functions rather than calling them directly.\n\n\nAt this stage we now have a defined set of methods needed for a refs\nbackend and we can start building and adding new types of ref backends\nto git.\n\n\nVersion 3:\n- Rework the patches so that we host the common functions in refs.c\n  instead of refs-common.c\nVersion 2:\n- Do not use C99 style initializers as suggested by David Turner.\n- Make head_ref_namespaced a common function instead of a backend function\n\n\nRonnie Sahlberg (23):\n  refs.c: create a public function for is_refname_available\n  refs-be-files.c: rename refs to refs-be-files\n  refs.c: add a new refs.c file to hold all common refs code\n  refs.c: move update_ref to refs.c\n  refs.c: move delete_ref to the common code\n  refs.c: move rename_ref to the common code\n  refs.c: move read_ref_at to the common refs file\n  refs.c: move the hidden refs functions to the common code\n  refs.c: move dwim and friend functions to the common refs code\n  refs.c: move warn_if_dangling_symref* to the common code\n  refs.c: move read_ref, read_ref_full and ref_exists to the common code\n  refs.c: move resolve_refdup to common\n  refs.c: move check_refname_component to the common code\n  refs.c: move is_branch to the common code\n  refs.c: move names_conflict to the common code\n  refs.c: move prettify_refname to the common code\n  refs.c: move ref iterators to the common code\n  refs.c: move head_ref_namespaced to the common code\n  refs-be-files.c: add a backend method structure with transaction\n    functions\n  refs-be-files.c: add reflog backend methods\n  refs-be-files.c: add methods for misc ref operations\n  refs-be-files.c: add methods for head_ref*\n  refs-be-files.c: add methods for the ref iterators\n\n Makefile        |    1 +\n refs-be-files.c | 3330 +++++++++++++++++++++++++++++++++++++++++\n refs.c          | 4457 +++++++++----------------------------------------------\n refs.h          |  107 ++\n 4 files changed, 4110 insertions(+), 3785 deletions(-)\n create mode 100644 refs-be-files.c\n\n-- \n2.0.1.552.g1af257a\n"},{"id":"247929","messageId":"1408465847-30384-2-git-send-email-sahlberg@google.com","threadId":"37379","inReplyTo":"1408465847-30384-1-git-send-email-sahlberg@google.com","subject":"[PATCH v3 01/23] refs.c: create a public function for is_refname_available","fromName":"Ronnie Sahlberg","fromEmail":"sahlberg@google.com","sentAt":"2014-08-19T16:30:25Z","receivedAt":"2014-08-19T16:30:25Z","isPatch":true,"sender":{"key":"sahlberg@google.com","avatar":"https://avatars.githubusercontent.com/u/7320636?v=4"},"body":"Export a generic is_refname_available() function. We will need this\nas a public shared function later when we add additional refs backends\nsince we want to keep using the same rules for ref naming across\nall backends.\n\nSigned-off-by: Ronnie Sahlberg <sahlberg@google.com>\n---\n refs.c | 29 ++++++++++++++++++-----------\n refs.h |  6 ++++++\n 2 files changed, 24 insertions(+), 11 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 7e13c0f..4a22513 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -830,9 +830,9 @@ static int name_conflict_fn(struct ref_entry *entry, void *cb_data)\n  * operation). skip contains a list of refs we want to skip checking for\n  * conflicts with.\n  */\n-static int is_refname_available(const char *refname,\n-\t\t\t\tstruct ref_dir *dir,\n-\t\t\t\tconst char **skip, int skipnum)\n+static int is_refname_available_dir(const char *refname,\n+\t\t\t\t    struct ref_dir *dir,\n+\t\t\t\t    const char **skip, int skipnum)\n {\n \tstruct name_conflict_cb data;\n \tdata.refname = refname;\n@@ -1238,6 +1238,18 @@ static struct ref_dir *get_loose_refs(struct ref_cache *refs)\n \treturn get_ref_dir(refs->loose);\n }\n \n+int is_refname_available(const char *refname, const char **skip, int skipnum)\n+{\n+\tif (!is_refname_available_dir(refname, get_packed_refs(&ref_cache),\n+\t\t\t\t      skip, skipnum))\n+\t\treturn 0;\n+\n+\tif (!is_refname_available_dir(refname, get_loose_refs(&ref_cache),\n+\t\t\t\t      skip, skipnum))\n+\t\treturn 0;\n+\treturn 1;\n+}\n+\n /* We allow \"recursive\" symbolic refs. Only within reason, though */\n #define MAXDEPTH 5\n #define MAXREFLEN (1024)\n@@ -2168,8 +2180,8 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,\n \t * name is a proper prefix of our refname.\n \t */\n \tif (missing &&\n-\t     !is_refname_available(refname, get_packed_refs(&ref_cache),\n-\t\t\t\t   skip, skipnum)) {\n+\t     !is_refname_available_dir(refname, get_packed_refs(&ref_cache),\n+\t\t\t\t       skip, skipnum)) {\n \t\tlast_errno = ENOTDIR;\n \t\tgoto error_return;\n \t}\n@@ -2676,12 +2688,7 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms\n \t\treturn 1;\n \t}\n \n-\tif (!is_refname_available(newrefname, get_packed_refs(&ref_cache),\n-\t\t\t\t  &oldrefname, 1))\n-\t\treturn 1;\n-\n-\tif (!is_refname_available(newrefname, get_loose_refs(&ref_cache),\n-\t\t\t\t  &oldrefname, 1))\n+\tif (!is_refname_available(newrefname, &oldrefname, 1))\n \t\treturn 1;\n \n \tlog = reflog_exists(oldrefname);\ndiff --git a/refs.h b/refs.h\nindex f44b5c8..d526da0 100644\n--- a/refs.h\n+++ b/refs.h\n@@ -131,6 +131,12 @@ extern int ref_exists(const char *);\n extern int is_branch(const char *refname);\n \n /*\n+ * Check that a particular refname is available for creation. skip contains\n+ * a list of refnames to exclude from the refname collision tests.\n+ */\n+int is_refname_available(const char *refname, const char **skip, int skipnum);\n+\n+/*\n  * If refname is a non-symbolic reference that refers to a tag object,\n  * and the tag can be (recursively) dereferenced to a non-tag object,\n  * store the SHA1 of the referred-to object to sha1 and return 0.  If\n-- \n2.0.1.552.g1af257a\n"},{"id":"247943","messageId":"1408465847-30384-4-git-send-email-sahlberg@google.com","threadId":"37379","inReplyTo":"1408465847-30384-1-git-send-email-sahlberg@google.com","subject":"[PATCH v3 03/23] refs.c: add a new refs.c file to hold all common refs code","fromName":"Ronnie Sahlberg","fromEmail":"sahlberg@google.com","sentAt":"2014-08-19T16:30:27Z","receivedAt":"2014-08-19T16:30:27Z","isPatch":true,"sender":{"key":"sahlberg@google.com","avatar":"https://avatars.githubusercontent.com/u/7320636?v=4"},"body":"Create a new erfs.c file that will be used to hold all the refs\ncode that is backend agnostic and will be shared across all backends.\n\nThe reason we renamed everything to refs-be-files.c in the previous patch\nand now start moving the common code back to the new refs.c file\ninstead of the other way around is the etive volumes of code.\n\nWith the ref_cache, packed refs and loose ref handling that are all\npart of the files based implementation the backend specific part\nof the old refs.c file is several times larger than the backend agnostic\npart. Therefore it makes more sense to first rename everything to be\npart of the files based backend and then move the parts that can be used\nas common code back to refs.c.\n\nSigned-off-by: Ronnie Sahlberg <sahlberg@google.com>\n---\n Makefile | 1 +\n refs.c   | 3 +++\n 2 files changed, 4 insertions(+)\n create mode 100644 refs.c\n\ndiff --git a/Makefile b/Makefile\nindex e010ad1..937d22a 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -857,6 +857,7 @@ LIB_OBJS += quote.o\n LIB_OBJS += reachable.o\n LIB_OBJS += read-cache.o\n LIB_OBJS += reflog-walk.o\n+LIB_OBJS += refs.o\n LIB_OBJS += refs-be-files.o\n LIB_OBJS += remote.o\n LIB_OBJS += replace_object.o\ndiff --git a/refs.c b/refs.c\nnew file mode 100644\nindex 0000000..77492ff\n--- /dev/null\n+++ b/refs.c\n@@ -0,0 +1,3 @@\n+/*\n+ * Common refs code for all backends.\n+ */\n-- \n2.0.1.552.g1af257a\n"},{"id":"247928","messageId":"1408465847-30384-5-git-send-email-sahlberg@google.com","threadId":"37379","inReplyTo":"1408465847-30384-1-git-send-email-sahlberg@google.com","subject":"[PATCH v3 04/23] refs.c: move update_ref to refs.c","fromName":"Ronnie Sahlberg","fromEmail":"sahlberg@google.com","sentAt":"2014-08-19T16:30:28Z","receivedAt":"2014-08-19T16:30:28Z","isPatch":true,"sender":{"key":"sahlberg@google.com","avatar":"https://avatars.githubusercontent.com/u/7320636?v=4"},"body":"This change moves update_ref() to the refs.c file since this function\ndoes not contain any backend specific code.\n\nSigned-off-by: Ronnie Sahlberg <sahlberg@google.com>\n---\n refs-be-files.c | 23 -----------------------\n refs.c          | 25 +++++++++++++++++++++++++\n 2 files changed, 25 insertions(+), 23 deletions(-)\n\ndiff --git a/refs-be-files.c b/refs-be-files.c\nindex 4a22513..eb66cf7 100644\n--- a/refs-be-files.c\n+++ b/refs-be-files.c\n@@ -3576,29 +3576,6 @@ int transaction_delete_sha1(struct ref_transaction *transaction,\n \t\t\t\t      old_sha1, flags, have_old, msg, err);\n }\n \n-int update_ref(const char *action, const char *refname,\n-\t       const unsigned char *sha1, const unsigned char *oldval,\n-\t       int flags, struct strbuf *e)\n-{\n-\tstruct ref_transaction *t;\n-\tstruct strbuf err = STRBUF_INIT;\n-\n-\tt = transaction_begin(&err);\n-\tif (!t ||\n-\t    transaction_update_sha1(t, refname, sha1, oldval, flags,\n-\t\t\t\t    !!oldval, action, &err) ||\n-\t    transaction_commit(t, &err)) {\n-\t\tconst char *str = \"update_ref failed for ref '%s': %s\";\n-\n-\t\ttransaction_free(t);\n-\t\tif (e)\n-\t\t\tstrbuf_addf(e, str, refname, err.buf);\n-\t\tstrbuf_release(&err);\n-\t\treturn 1;\n-\t}\n-\treturn 0;\n-}\n-\n static int ref_update_compare(const void *r1, const void *r2)\n {\n \tconst struct ref_update * const *u1 = r1;\ndiff --git a/refs.c b/refs.c\nindex 77492ff..5f6a1e7 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -1,3 +1,28 @@\n /*\n  * Common refs code for all backends.\n  */\n+#include \"cache.h\"\n+#include \"refs.h\"\n+\n+int update_ref(const char *action, const char *refname,\n+\t       const unsigned char *sha1, const unsigned char *oldval,\n+\t       int flags, struct strbuf *e)\n+{\n+\tstruct ref_transaction *t;\n+\tstruct strbuf err = STRBUF_INIT;\n+\n+\tt = transaction_begin(&err);\n+\tif (!t ||\n+\t    transaction_update_sha1(t, refname, sha1, oldval, flags,\n+\t\t\t\t    !!oldval, action, &err) ||\n+\t    transaction_commit(t, &err)) {\n+\t\tconst char *str = \"update_ref failed for ref '%s': %s\";\n+\n+\t\ttransaction_free(t);\n+\t\tif (e)\n+\t\t\tstrbuf_addf(e, str, refname, err.buf);\n+\t\tstrbuf_release(&err);\n+\t\treturn 1;\n+\t}\n+\treturn 0;\n+}\n-- \n2.0.1.552.g1af257a\n"},{"id":"247927","messageId":"1408465847-30384-6-git-send-email-sahlberg@google.com","threadId":"37379","inReplyTo":"1408465847-30384-1-git-send-email-sahlberg@google.com","subject":"[PATCH v3 05/23] refs.c: move delete_ref to the common code","fromName":"Ronnie Sahlberg","fromEmail":"sahlberg@google.com","sentAt":"2014-08-19T16:30:29Z","receivedAt":"2014-08-19T16:30:29Z","isPatch":true,"sender":{"key":"sahlberg@google.com","avatar":"https://avatars.githubusercontent.com/u/7320636?v=4"},"body":"This change moves delete_ref() to the refs.c file since this function\ndoes not contain any backend specific code.\n\nSigned-off-by: Ronnie Sahlberg <sahlberg@google.com>\n---\n refs-be-files.c | 19 -------------------\n refs.c          | 19 +++++++++++++++++++\n 2 files changed, 19 insertions(+), 19 deletions(-)\n\ndiff --git a/refs-be-files.c b/refs-be-files.c\nindex eb66cf7..faf794c 100644\n--- a/refs-be-files.c\n+++ b/refs-be-files.c\n@@ -2622,25 +2622,6 @@ static int delete_ref_loose(struct ref_lock *lock, int flag, struct strbuf *err)\n \treturn 0;\n }\n \n-int delete_ref(const char *refname, const unsigned char *sha1, int delopt)\n-{\n-\tstruct ref_transaction *transaction;\n-\tstruct strbuf err = STRBUF_INIT;\n-\n-\ttransaction = transaction_begin(&err);\n-\tif (!transaction ||\n-\t    transaction_delete_sha1(transaction, refname, sha1, delopt,\n-\t\t\t\t    sha1 && !is_null_sha1(sha1), NULL, &err) ||\n-\t    transaction_commit(transaction, &err)) {\n-\t\terror(\"%s\", err.buf);\n-\t\ttransaction_free(transaction);\n-\t\tstrbuf_release(&err);\n-\t\treturn 1;\n-\t}\n-\ttransaction_free(transaction);\n-\treturn 0;\n-}\n-\n struct rename_reflog_cb {\n \tstruct ref_transaction *transaction;\n \tconst char *refname;\ndiff --git a/refs.c b/refs.c\nindex 5f6a1e7..70b12eb 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -26,3 +26,22 @@ int update_ref(const char *action, const char *refname,\n \t}\n \treturn 0;\n }\n+\n+int delete_ref(const char *refname, const unsigned char *sha1, int delopt)\n+{\n+\tstruct ref_transaction *transaction;\n+\tstruct strbuf err = STRBUF_INIT;\n+\n+\ttransaction = transaction_begin(&err);\n+\tif (!transaction ||\n+\t    transaction_delete_sha1(transaction, refname, sha1, delopt,\n+\t\t\t\t    sha1 && !is_null_sha1(sha1), NULL, &err) ||\n+\t    transaction_commit(transaction, &err)) {\n+\t\terror(\"%s\", err.buf);\n+\t\ttransaction_free(transaction);\n+\t\tstrbuf_release(&err);\n+\t\treturn 1;\n+\t}\n+\ttransaction_free(transaction);\n+\treturn 0;\n+}\n-- \n2.0.1.552.g1af257a\n"},{"id":"247926","messageId":"1408465847-30384-7-git-send-email-sahlberg@google.com","threadId":"37379","inReplyTo":"1408465847-30384-1-git-send-email-sahlberg@google.com","subject":"[PATCH v3 06/23] refs.c: move rename_ref to the common code","fromName":"Ronnie Sahlberg","fromEmail":"sahlberg@google.com","sentAt":"2014-08-19T16:30:30Z","receivedAt":"2014-08-19T16:30:30Z","isPatch":true,"sender":{"key":"sahlberg@google.com","avatar":"https://avatars.githubusercontent.com/u/7320636?v=4"},"body":"This change moves rename_ref() to the refs.c file since this function\ndoes not contain any backend specific code.\n\nSigned-off-by: Ronnie Sahlberg <sahlberg@google.com>\n---\n refs-be-files.c | 92 ---------------------------------------------------------\n refs.c          | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 92 insertions(+), 92 deletions(-)\n\ndiff --git a/refs-be-files.c b/refs-be-files.c\nindex faf794c..7d579be 100644\n--- a/refs-be-files.c\n+++ b/refs-be-files.c\n@@ -2622,98 +2622,6 @@ static int delete_ref_loose(struct ref_lock *lock, int flag, struct strbuf *err)\n \treturn 0;\n }\n \n-struct rename_reflog_cb {\n-\tstruct ref_transaction *transaction;\n-\tconst char *refname;\n-\tstruct strbuf *err;\n-};\n-\n-static int rename_reflog_ent(unsigned char *osha1, unsigned char *nsha1,\n-\t\t\t     const char *id, unsigned long timestamp, int tz,\n-\t\t\t     const char *message, void *cb_data)\n-{\n-\tstruct rename_reflog_cb *cb = cb_data;\n-\tstruct reflog_committer_info ci;\n-\n-\tmemset(&ci, 0, sizeof(ci));\n-\tci.id = id;\n-\tci.timestamp = timestamp;\n-\tci.tz = tz;\n-\treturn transaction_update_reflog(cb->transaction, cb->refname,\n-\t\t\t\t\t nsha1, osha1, &ci, message, 0,\n-\t\t\t\t\t cb->err);\n-}\n-\n-int rename_ref(const char *oldrefname, const char *newrefname, const char *logmsg)\n-{\n-\tunsigned char sha1[20];\n-\tint flag = 0, log;\n-\tstruct ref_transaction *transaction = NULL;\n-\tstruct strbuf err = STRBUF_INIT;\n-\tconst char *symref = NULL;\n-\tstruct rename_reflog_cb cb;\n-\tstruct reflog_committer_info ci;\n-\n-\tmemset(&ci, 0, sizeof(ci));\n-\tci.committer_info = git_committer_info(0);\n-\n-\tsymref = resolve_ref_unsafe(oldrefname, sha1,\n-\t\t\t\t    RESOLVE_REF_READING, &flag);\n-\tif (flag & REF_ISSYMREF) {\n-\t\terror(\"refname %s is a symbolic ref, renaming it is not supported\",\n-\t\t\toldrefname);\n-\t\treturn 1;\n-\t}\n-\tif (!symref) {\n-\t\terror(\"refname %s not found\", oldrefname);\n-\t\treturn 1;\n-\t}\n-\n-\tif (!is_refname_available(newrefname, &oldrefname, 1))\n-\t\treturn 1;\n-\n-\tlog = reflog_exists(oldrefname);\n-\ttransaction = transaction_begin(&err);\n-\tif (!transaction)\n-\t\tgoto fail;\n-\n-\tif (strcmp(oldrefname, newrefname)) {\n-\t\tif (log && transaction_update_reflog(transaction, newrefname,\n-\t\t\t\t\t\t     sha1, sha1, &ci, NULL,\n-\t\t\t\t\t\t     REFLOG_TRUNCATE, &err))\n-\t\t\tgoto fail;\n-\t\tcb.transaction = transaction;\n-\t\tcb.refname = newrefname;\n-\t\tcb.err = &err;\n-\t\tif (log && for_each_reflog_ent(oldrefname, rename_reflog_ent,\n-\t\t\t\t\t       &cb))\n-\t\t\tgoto fail;\n-\n-\t\tif (transaction_delete_sha1(transaction, oldrefname, sha1,\n-\t\t\t\t\t    REF_NODEREF,\n-\t\t\t\t\t    1, NULL, &err))\n-\t\t\tgoto fail;\n-\t}\n-\tif (transaction_update_sha1(transaction, newrefname, sha1,\n-\t\t\t\t    NULL, 0, 0, NULL, &err))\n-\t\tgoto fail;\n-\tif (log && transaction_update_reflog(transaction, newrefname, sha1,\n-\t\t\t\t\t     sha1, &ci, logmsg,\n-\t\t\t\t\t     REFLOG_COMMITTER_INFO_IS_VALID,\n-\t\t\t\t\t     &err))\n-\t\tgoto fail;\n-\tif (transaction_commit(transaction, &err))\n-\t\tgoto fail;\n-\ttransaction_free(transaction);\n-\treturn 0;\n-\n- fail:\n-\terror(\"rename_ref failed: %s\", err.buf);\n-\tstrbuf_release(&err);\n-\ttransaction_free(transaction);\n-\treturn 1;\n-}\n-\n static int close_ref(struct ref_lock *lock)\n {\n \tif (close_lock_file(lock->lk))\ndiff --git a/refs.c b/refs.c\nindex 70b12eb..319eafa 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -45,3 +45,95 @@ int delete_ref(const char *refname, const unsigned char *sha1, int delopt)\n \ttransaction_free(transaction);\n \treturn 0;\n }\n+\n+struct rename_reflog_cb {\n+\tstruct ref_transaction *transaction;\n+\tconst char *refname;\n+\tstruct strbuf *err;\n+};\n+\n+static int rename_reflog_ent(unsigned char *osha1, unsigned char *nsha1,\n+\t\t\t     const char *id, unsigned long timestamp, int tz,\n+\t\t\t     const char *message, void *cb_data)\n+{\n+\tstruct rename_reflog_cb *cb = cb_data;\n+\tstruct reflog_committer_info ci;\n+\n+\tmemset(&ci, 0, sizeof(ci));\n+\tci.id = id;\n+\tci.timestamp = timestamp;\n+\tci.tz = tz;\n+\treturn transaction_update_reflog(cb->transaction, cb->refname,\n+\t\t\t\t\t nsha1, osha1, &ci, message, 0,\n+\t\t\t\t\t cb->err);\n+}\n+\n+int rename_ref(const char *oldrefname, const char *newrefname, const char *logmsg)\n+{\n+\tunsigned char sha1[20];\n+\tint flag = 0, log;\n+\tstruct ref_transaction *transaction = NULL;\n+\tstruct strbuf err = STRBUF_INIT;\n+\tconst char *symref = NULL;\n+\tstruct rename_reflog_cb cb;\n+\tstruct reflog_committer_info ci;\n+\n+\tmemset(&ci, 0, sizeof(ci));\n+\tci.committer_info = git_committer_info(0);\n+\n+\tsymref = resolve_ref_unsafe(oldrefname, sha1,\n+\t\t\t\t    RESOLVE_REF_READING, &flag);\n+\tif (flag & REF_ISSYMREF) {\n+\t\terror(\"refname %s is a symbolic ref, renaming it is not supported\",\n+\t\t\toldrefname);\n+\t\treturn 1;\n+\t}\n+\tif (!symref) {\n+\t\terror(\"refname %s not found\", oldrefname);\n+\t\treturn 1;\n+\t}\n+\n+\tif (!is_refname_available(newrefname, &oldrefname, 1))\n+\t\treturn 1;\n+\n+\tlog = reflog_exists(oldrefname);\n+\ttransaction = transaction_begin(&err);\n+\tif (!transaction)\n+\t\tgoto fail;\n+\n+\tif (strcmp(oldrefname, newrefname)) {\n+\t\tif (log && transaction_update_reflog(transaction, newrefname,\n+\t\t\t\t\t\t     sha1, sha1, &ci, NULL,\n+\t\t\t\t\t\t     REFLOG_TRUNCATE, &err))\n+\t\t\tgoto fail;\n+\t\tcb.transaction = transaction;\n+\t\tcb.refname = newrefname;\n+\t\tcb.err = &err;\n+\t\tif (log && for_each_reflog_ent(oldrefname, rename_reflog_ent,\n+\t\t\t\t\t       &cb))\n+\t\t\tgoto fail;\n+\n+\t\tif (transaction_delete_sha1(transaction, oldrefname, sha1,\n+\t\t\t\t\t    REF_NODEREF,\n+\t\t\t\t\t    1, NULL, &err))\n+\t\t\tgoto fail;\n+\t}\n+\tif (transaction_update_sha1(transaction, newrefname, sha1,\n+\t\t\t\t    NULL, 0, 0, NULL, &err))\n+\t\tgoto fail;\n+\tif (log && transaction_update_reflog(transaction, newrefname, sha1,\n+\t\t\t\t\t     sha1, &ci, logmsg,\n+\t\t\t\t\t     REFLOG_COMMITTER_INFO_IS_VALID,\n+\t\t\t\t\t     &err))\n+\t\tgoto fail;\n+\tif (transaction_commit(transaction, &err))\n+\t\tgoto fail;\n+\ttransaction_free(transaction);\n+\treturn 0;\n+\n+ fail:\n+\terror(\"rename_ref failed: %s\", err.buf);\n+\tstrbuf_release(&err);\n+\ttransaction_free(transaction);\n+\treturn 1;\n+}\n-- \n2.0.1.552.g1af257a\n"},{"id":"247934","messageId":"1408465847-30384-8-git-send-email-sahlberg@google.com","threadId":"37379","inReplyTo":"1408465847-30384-1-git-send-email-sahlberg@google.com","subject":"[PATCH v3 07/23] refs.c: move read_ref_at to the common refs file","fromName":"Ronnie Sahlberg","fromEmail":"sahlberg@google.com","sentAt":"2014-08-19T16:30:31Z","receivedAt":"2014-08-19T16:30:31Z","isPatch":true,"sender":{"key":"sahlberg@google.com","avatar":"https://avatars.githubusercontent.com/u/7320636?v=4"},"body":"This change moves read_ref_at() to the refs.c file since this function\ndoes not contain any backend specific code.\n\nSigned-off-by: Ronnie Sahlberg <sahlberg@google.com>\n---\n refs-be-files.c | 114 --------------------------------------------------------\n refs.c          | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 114 insertions(+), 114 deletions(-)\n\ndiff --git a/refs-be-files.c b/refs-be-files.c\nindex 7d579be..52ca0bb 100644\n--- a/refs-be-files.c\n+++ b/refs-be-files.c\n@@ -2935,120 +2935,6 @@ int create_symref(const char *ref_target, const char *refs_heads_master,\n \treturn 0;\n }\n \n-struct read_ref_at_cb {\n-\tconst char *refname;\n-\tunsigned long at_time;\n-\tint cnt;\n-\tint reccnt;\n-\tunsigned char *sha1;\n-\tint found_it;\n-\n-\tunsigned char osha1[20];\n-\tunsigned char nsha1[20];\n-\tint tz;\n-\tunsigned long date;\n-\tchar **msg;\n-\tunsigned long *cutoff_time;\n-\tint *cutoff_tz;\n-\tint *cutoff_cnt;\n-};\n-\n-static int read_ref_at_ent(unsigned char *osha1, unsigned char *nsha1,\n-\t\tconst char *id, unsigned long timestamp, int tz,\n-\t\tconst char *message, void *cb_data)\n-{\n-\tstruct read_ref_at_cb *cb = cb_data;\n-\n-\tcb->reccnt++;\n-\tcb->tz = tz;\n-\tcb->date = timestamp;\n-\n-\tif (timestamp <= cb->at_time || cb->cnt == 0) {\n-\t\tif (cb->msg)\n-\t\t\t*cb->msg = xstrdup(message);\n-\t\tif (cb->cutoff_time)\n-\t\t\t*cb->cutoff_time = timestamp;\n-\t\tif (cb->cutoff_tz)\n-\t\t\t*cb->cutoff_tz = tz;\n-\t\tif (cb->cutoff_cnt)\n-\t\t\t*cb->cutoff_cnt = cb->reccnt - 1;\n-\t\t/*\n-\t\t * we have not yet updated cb->[n|o]sha1 so they still\n-\t\t * hold the values for the previous record.\n-\t\t */\n-\t\tif (!is_null_sha1(cb->osha1)) {\n-\t\t\thashcpy(cb->sha1, nsha1);\n-\t\t\tif (hashcmp(cb->osha1, nsha1))\n-\t\t\t\twarning(\"Log for ref %s has gap after %s.\",\n-\t\t\t\t\tcb->refname, show_date(cb->date, cb->tz, DATE_RFC2822));\n-\t\t}\n-\t\telse if (cb->date == cb->at_time)\n-\t\t\thashcpy(cb->sha1, nsha1);\n-\t\telse if (hashcmp(nsha1, cb->sha1))\n-\t\t\twarning(\"Log for ref %s unexpectedly ended on %s.\",\n-\t\t\t\tcb->refname, show_date(cb->date, cb->tz,\n-\t\t\t\t\t\t   DATE_RFC2822));\n-\t\thashcpy(cb->osha1, osha1);\n-\t\thashcpy(cb->nsha1, nsha1);\n-\t\tcb->found_it = 1;\n-\t\treturn 1;\n-\t}\n-\thashcpy(cb->osha1, osha1);\n-\thashcpy(cb->nsha1, nsha1);\n-\tif (cb->cnt > 0)\n-\t\tcb->cnt--;\n-\treturn 0;\n-}\n-\n-static int read_ref_at_ent_oldest(unsigned char *osha1, unsigned char *nsha1,\n-\t\t\t\t  const char *id, unsigned long timestamp,\n-\t\t\t\t  int tz, const char *message, void *cb_data)\n-{\n-\tstruct read_ref_at_cb *cb = cb_data;\n-\n-\tif (cb->msg)\n-\t\t*cb->msg = xstrdup(message);\n-\tif (cb->cutoff_time)\n-\t\t*cb->cutoff_time = timestamp;\n-\tif (cb->cutoff_tz)\n-\t\t*cb->cutoff_tz = tz;\n-\tif (cb->cutoff_cnt)\n-\t\t*cb->cutoff_cnt = cb->reccnt;\n-\thashcpy(cb->sha1, osha1);\n-\tif (is_null_sha1(cb->sha1))\n-\t\thashcpy(cb->sha1, nsha1);\n-\t/* We just want the first entry */\n-\treturn 1;\n-}\n-\n-int read_ref_at(const char *refname, unsigned long at_time, int cnt,\n-\t\tunsigned char *sha1, char **msg,\n-\t\tunsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt)\n-{\n-\tstruct read_ref_at_cb cb;\n-\n-\tmemset(&cb, 0, sizeof(cb));\n-\tcb.refname = refname;\n-\tcb.at_time = at_time;\n-\tcb.cnt = cnt;\n-\tcb.msg = msg;\n-\tcb.cutoff_time = cutoff_time;\n-\tcb.cutoff_tz = cutoff_tz;\n-\tcb.cutoff_cnt = cutoff_cnt;\n-\tcb.sha1 = sha1;\n-\n-\tfor_each_reflog_ent_reverse(refname, read_ref_at_ent, &cb);\n-\n-\tif (!cb.reccnt)\n-\t\tdie(\"Log for %s is empty.\", refname);\n-\tif (cb.found_it)\n-\t\treturn 0;\n-\n-\tfor_each_reflog_ent(refname, read_ref_at_ent_oldest, &cb);\n-\n-\treturn 1;\n-}\n-\n int reflog_exists(const char *refname)\n {\n \tstruct stat st;\ndiff --git a/refs.c b/refs.c\nindex 319eafa..072cd39 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -137,3 +137,117 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms\n \ttransaction_free(transaction);\n \treturn 1;\n }\n+\n+struct read_ref_at_cb {\n+\tconst char *refname;\n+\tunsigned long at_time;\n+\tint cnt;\n+\tint reccnt;\n+\tunsigned char *sha1;\n+\tint found_it;\n+\n+\tunsigned char osha1[20];\n+\tunsigned char nsha1[20];\n+\tint tz;\n+\tunsigned long date;\n+\tchar **msg;\n+\tunsigned long *cutoff_time;\n+\tint *cutoff_tz;\n+\tint *cutoff_cnt;\n+};\n+\n+static int read_ref_at_ent(unsigned char *osha1, unsigned char *nsha1,\n+\t\tconst char *id, unsigned long timestamp, int tz,\n+\t\tconst char *message, void *cb_data)\n+{\n+\tstruct read_ref_at_cb *cb = cb_data;\n+\n+\tcb->reccnt++;\n+\tcb->tz = tz;\n+\tcb->date = timestamp;\n+\n+\tif (timestamp <= cb->at_time || cb->cnt == 0) {\n+\t\tif (cb->msg)\n+\t\t\t*cb->msg = xstrdup(message);\n+\t\tif (cb->cutoff_time)\n+\t\t\t*cb->cutoff_time = timestamp;\n+\t\tif (cb->cutoff_tz)\n+\t\t\t*cb->cutoff_tz = tz;\n+\t\tif (cb->cutoff_cnt)\n+\t\t\t*cb->cutoff_cnt = cb->reccnt - 1;\n+\t\t/*\n+\t\t * we have not yet updated cb->[n|o]sha1 so they still\n+\t\t * hold the values for the previous record.\n+\t\t */\n+\t\tif (!is_null_sha1(cb->osha1)) {\n+\t\t\thashcpy(cb->sha1, nsha1);\n+\t\t\tif (hashcmp(cb->osha1, nsha1))\n+\t\t\t\twarning(\"Log for ref %s has gap after %s.\",\n+\t\t\t\t\tcb->refname, show_date(cb->date, cb->tz, DATE_RFC2822));\n+\t\t}\n+\t\telse if (cb->date == cb->at_time)\n+\t\t\thashcpy(cb->sha1, nsha1);\n+\t\telse if (hashcmp(nsha1, cb->sha1))\n+\t\t\twarning(\"Log for ref %s unexpectedly ended on %s.\",\n+\t\t\t\tcb->refname, show_date(cb->date, cb->tz,\n+\t\t\t\t\t\t   DATE_RFC2822));\n+\t\thashcpy(cb->osha1, osha1);\n+\t\thashcpy(cb->nsha1, nsha1);\n+\t\tcb->found_it = 1;\n+\t\treturn 1;\n+\t}\n+\thashcpy(cb->osha1, osha1);\n+\thashcpy(cb->nsha1, nsha1);\n+\tif (cb->cnt > 0)\n+\t\tcb->cnt--;\n+\treturn 0;\n+}\n+\n+static int read_ref_at_ent_oldest(unsigned char *osha1, unsigned char *nsha1,\n+\t\t\t\t  const char *id, unsigned long timestamp,\n+\t\t\t\t  int tz, const char *message, void *cb_data)\n+{\n+\tstruct read_ref_at_cb *cb = cb_data;\n+\n+\tif (cb->msg)\n+\t\t*cb->msg = xstrdup(message);\n+\tif (cb->cutoff_time)\n+\t\t*cb->cutoff_time = timestamp;\n+\tif (cb->cutoff_tz)\n+\t\t*cb->cutoff_tz = tz;\n+\tif (cb->cutoff_cnt)\n+\t\t*cb->cutoff_cnt = cb->reccnt;\n+\thashcpy(cb->sha1, osha1);\n+\tif (is_null_sha1(cb->sha1))\n+\t\thashcpy(cb->sha1, nsha1);\n+\t/* We just want the first entry */\n+\treturn 1;\n+}\n+\n+int read_ref_at(const char *refname, unsigned long at_time, int cnt,\n+\t\tunsigned char *sha1, char **msg,\n+\t\tunsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt)\n+{\n+\tstruct read_ref_at_cb cb;\n+\n+\tmemset(&cb, 0, sizeof(cb));\n+\tcb.refname = refname;\n+\tcb.at_time = at_time;\n+\tcb.cnt = cnt;\n+\tcb.msg = msg;\n+\tcb.cutoff_time = cutoff_time;\n+\tcb.cutoff_tz = cutoff_tz;\n+\tcb.cutoff_cnt = cutoff_cnt;\n+\tcb.sha1 = sha1;\n+\n+\tfor_each_reflog_ent_reverse(refname, read_ref_at_ent, &cb);\n+\n+\tif (!cb.reccnt)\n+\t\tdie(\"Log for %s is empty.\", refname);\n+\tif (cb.found_it)\n+\t\treturn 0;\n+\n+\tfor_each_reflog_ent(refname, read_ref_at_ent_oldest, &cb);\n+\n+\treturn 1;\n+}\n-- \n2.0.1.552.g1af257a\n"},{"id":"247941","messageId":"1408465847-30384-9-git-send-email-sahlberg@google.com","threadId":"37379","inReplyTo":"1408465847-30384-1-git-send-email-sahlberg@google.com","subject":"[PATCH v3 08/23] refs.c: move the hidden refs functions to the common code","fromName":"Ronnie Sahlberg","fromEmail":"sahlberg@google.com","sentAt":"2014-08-19T16:30:32Z","receivedAt":"2014-08-19T16:30:32Z","isPatch":true,"sender":{"key":"sahlberg@google.com","avatar":"https://avatars.githubusercontent.com/u/7320636?v=4"},"body":"This change moves the hidden refs functions to the refs.c file since\nthese functions do not contain any backend specific code.\n\nSigned-off-by: Ronnie Sahlberg <sahlberg@google.com>\n---\n refs-be-files.c | 43 -------------------------------------------\n refs.c          | 44 ++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 44 insertions(+), 43 deletions(-)\n\ndiff --git a/refs-be-files.c b/refs-be-files.c\nindex 52ca0bb..6181edf 100644\n--- a/refs-be-files.c\n+++ b/refs-be-files.c\n@@ -3796,46 +3796,3 @@ char *shorten_unambiguous_ref(const char *refname, int strict)\n \tfree(short_name);\n \treturn xstrdup(refname);\n }\n-\n-static struct string_list *hide_refs;\n-\n-int parse_hide_refs_config(const char *var, const char *value, const char *section)\n-{\n-\tif (!strcmp(\"transfer.hiderefs\", var) ||\n-\t    /* NEEDSWORK: use parse_config_key() once both are merged */\n-\t    (starts_with(var, section) && var[strlen(section)] == '.' &&\n-\t     !strcmp(var + strlen(section), \".hiderefs\"))) {\n-\t\tchar *ref;\n-\t\tint len;\n-\n-\t\tif (!value)\n-\t\t\treturn config_error_nonbool(var);\n-\t\tref = xstrdup(value);\n-\t\tlen = strlen(ref);\n-\t\twhile (len && ref[len - 1] == '/')\n-\t\t\tref[--len] = '\\0';\n-\t\tif (!hide_refs) {\n-\t\t\thide_refs = xcalloc(1, sizeof(*hide_refs));\n-\t\t\thide_refs->strdup_strings = 1;\n-\t\t}\n-\t\tstring_list_append(hide_refs, ref);\n-\t}\n-\treturn 0;\n-}\n-\n-int ref_is_hidden(const char *refname)\n-{\n-\tstruct string_list_item *item;\n-\n-\tif (!hide_refs)\n-\t\treturn 0;\n-\tfor_each_string_list_item(item, hide_refs) {\n-\t\tint len;\n-\t\tif (!starts_with(refname, item->string))\n-\t\t\tcontinue;\n-\t\tlen = strlen(item->string);\n-\t\tif (!refname[len] || refname[len] == '/')\n-\t\t\treturn 1;\n-\t}\n-\treturn 0;\n-}\ndiff --git a/refs.c b/refs.c\nindex 072cd39..9e2059b 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -3,6 +3,7 @@\n  */\n #include \"cache.h\"\n #include \"refs.h\"\n+#include \"string-list.h\"\n \n int update_ref(const char *action, const char *refname,\n \t       const unsigned char *sha1, const unsigned char *oldval,\n@@ -251,3 +252,46 @@ int read_ref_at(const char *refname, unsigned long at_time, int cnt,\n \n \treturn 1;\n }\n+\n+static struct string_list *hide_refs;\n+\n+int parse_hide_refs_config(const char *var, const char *value, const char *section)\n+{\n+\tif (!strcmp(\"transfer.hiderefs\", var) ||\n+\t    /* NEEDSWORK: use parse_config_key() once both are merged */\n+\t    (starts_with(var, section) && var[strlen(section)] == '.' &&\n+\t     !strcmp(var + strlen(section), \".hiderefs\"))) {\n+\t\tchar *ref;\n+\t\tint len;\n+\n+\t\tif (!value)\n+\t\t\treturn config_error_nonbool(var);\n+\t\tref = xstrdup(value);\n+\t\tlen = strlen(ref);\n+\t\twhile (len && ref[len - 1] == '/')\n+\t\t\tref[--len] = '\\0';\n+\t\tif (!hide_refs) {\n+\t\t\thide_refs = xcalloc(1, sizeof(*hide_refs));\n+\t\t\thide_refs->strdup_strings = 1;\n+\t\t}\n+\t\tstring_list_append(hide_refs, ref);\n+\t}\n+\treturn 0;\n+}\n+\n+int ref_is_hidden(const char *refname)\n+{\n+\tstruct string_list_item *item;\n+\n+\tif (!hide_refs)\n+\t\treturn 0;\n+\tfor_each_string_list_item(item, hide_refs) {\n+\t\tint len;\n+\t\tif (!starts_with(refname, item->string))\n+\t\t\tcontinue;\n+\t\tlen = strlen(item->string);\n+\t\tif (!refname[len] || refname[len] == '/')\n+\t\t\treturn 1;\n+\t}\n+\treturn 0;\n+}\n-- \n2.0.1.552.g1af257a\n"},{"id":"247946","messageId":"1408465847-30384-10-git-send-email-sahlberg@google.com","threadId":"37379","inReplyTo":"1408465847-30384-1-git-send-email-sahlberg@google.com","subject":"[PATCH v3 09/23] refs.c: move dwim and friend functions to the common refs code","fromName":"Ronnie Sahlberg","fromEmail":"sahlberg@google.com","sentAt":"2014-08-19T16:30:33Z","receivedAt":"2014-08-19T16:30:33Z","isPatch":true,"sender":{"key":"sahlberg@google.com","avatar":"https://avatars.githubusercontent.com/u/7320636?v=4"},"body":"These functions do not contain any backend specific code so we can move\nthem to the common code and share across all backends.\n\nSigned-off-by: Ronnie Sahlberg <sahlberg@google.com>\n---\n refs-be-files.c | 202 --------------------------------------------------------\n refs.c          | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 202 insertions(+), 202 deletions(-)\n\ndiff --git a/refs-be-files.c b/refs-be-files.c\nindex 6181edf..56e146f 100644\n--- a/refs-be-files.c\n+++ b/refs-be-files.c\n@@ -1956,30 +1956,6 @@ const char *prettify_refname(const char *name)\n \t\t0);\n }\n \n-static const char *ref_rev_parse_rules[] = {\n-\t\"%.*s\",\n-\t\"refs/%.*s\",\n-\t\"refs/tags/%.*s\",\n-\t\"refs/heads/%.*s\",\n-\t\"refs/remotes/%.*s\",\n-\t\"refs/remotes/%.*s/HEAD\",\n-\tNULL\n-};\n-\n-int refname_match(const char *abbrev_name, const char *full_name)\n-{\n-\tconst char **p;\n-\tconst int abbrev_name_len = strlen(abbrev_name);\n-\n-\tfor (p = ref_rev_parse_rules; *p; p++) {\n-\t\tif (!strcmp(full_name, mkpath(*p, abbrev_name_len, abbrev_name))) {\n-\t\t\treturn 1;\n-\t\t}\n-\t}\n-\n-\treturn 0;\n-}\n-\n static void unlock_ref(struct ref_lock *lock)\n {\n \t/* Do not free lock->lk -- atexit() still looks at them */\n@@ -2033,91 +2009,6 @@ static int remove_empty_directories(const char *file)\n \treturn result;\n }\n \n-/*\n- * *string and *len will only be substituted, and *string returned (for\n- * later free()ing) if the string passed in is a magic short-hand form\n- * to name a branch.\n- */\n-static char *substitute_branch_name(const char **string, int *len)\n-{\n-\tstruct strbuf buf = STRBUF_INIT;\n-\tint ret = interpret_branch_name(*string, *len, &buf);\n-\n-\tif (ret == *len) {\n-\t\tsize_t size;\n-\t\t*string = strbuf_detach(&buf, &size);\n-\t\t*len = size;\n-\t\treturn (char *)*string;\n-\t}\n-\n-\treturn NULL;\n-}\n-\n-int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)\n-{\n-\tchar *last_branch = substitute_branch_name(&str, &len);\n-\tconst char **p, *r;\n-\tint refs_found = 0;\n-\n-\t*ref = NULL;\n-\tfor (p = ref_rev_parse_rules; *p; p++) {\n-\t\tchar fullref[PATH_MAX];\n-\t\tunsigned char sha1_from_ref[20];\n-\t\tunsigned char *this_result;\n-\t\tint flag;\n-\n-\t\tthis_result = refs_found ? sha1_from_ref : sha1;\n-\t\tmksnpath(fullref, sizeof(fullref), *p, len, str);\n-\t\tr = resolve_ref_unsafe(fullref, this_result,\n-\t\t\t\t       RESOLVE_REF_READING, &flag);\n-\t\tif (r) {\n-\t\t\tif (!refs_found++)\n-\t\t\t\t*ref = xstrdup(r);\n-\t\t\tif (!warn_ambiguous_refs)\n-\t\t\t\tbreak;\n-\t\t} else if ((flag & REF_ISSYMREF) && strcmp(fullref, \"HEAD\")) {\n-\t\t\twarning(\"ignoring dangling symref %s.\", fullref);\n-\t\t} else if ((flag & REF_ISBROKEN) && strchr(fullref, '/')) {\n-\t\t\twarning(\"ignoring broken ref %s.\", fullref);\n-\t\t}\n-\t}\n-\tfree(last_branch);\n-\treturn refs_found;\n-}\n-\n-int dwim_log(const char *str, int len, unsigned char *sha1, char **log)\n-{\n-\tchar *last_branch = substitute_branch_name(&str, &len);\n-\tconst char **p;\n-\tint logs_found = 0;\n-\n-\t*log = NULL;\n-\tfor (p = ref_rev_parse_rules; *p; p++) {\n-\t\tunsigned char hash[20];\n-\t\tchar path[PATH_MAX];\n-\t\tconst char *ref, *it;\n-\n-\t\tmksnpath(path, sizeof(path), *p, len, str);\n-\t\tref = resolve_ref_unsafe(path, hash, RESOLVE_REF_READING, NULL);\n-\t\tif (!ref)\n-\t\t\tcontinue;\n-\t\tif (reflog_exists(path))\n-\t\t\tit = path;\n-\t\telse if (strcmp(ref, path) && reflog_exists(ref))\n-\t\t\tit = ref;\n-\t\telse\n-\t\t\tcontinue;\n-\t\tif (!logs_found++) {\n-\t\t\t*log = xstrdup(it);\n-\t\t\thashcpy(sha1, hash);\n-\t\t}\n-\t\tif (!warn_ambiguous_refs)\n-\t\t\tbreak;\n-\t}\n-\tfree(last_branch);\n-\treturn logs_found;\n-}\n-\n /* This function should make sure errno is meaningful on error */\n static struct ref_lock *lock_ref_sha1_basic(const char *refname,\n \t\t\t\t\t    const unsigned char *old_sha1,\n@@ -3703,96 +3594,3 @@ cleanup:\n \t\tret = -2;\n \treturn ret;\n }\n-\n-char *shorten_unambiguous_ref(const char *refname, int strict)\n-{\n-\tint i;\n-\tstatic char **scanf_fmts;\n-\tstatic int nr_rules;\n-\tchar *short_name;\n-\n-\tif (!nr_rules) {\n-\t\t/*\n-\t\t * Pre-generate scanf formats from ref_rev_parse_rules[].\n-\t\t * Generate a format suitable for scanf from a\n-\t\t * ref_rev_parse_rules rule by interpolating \"%s\" at the\n-\t\t * location of the \"%.*s\".\n-\t\t */\n-\t\tsize_t total_len = 0;\n-\t\tsize_t offset = 0;\n-\n-\t\t/* the rule list is NULL terminated, count them first */\n-\t\tfor (nr_rules = 0; ref_rev_parse_rules[nr_rules]; nr_rules++)\n-\t\t\t/* -2 for strlen(\"%.*s\") - strlen(\"%s\"); +1 for NUL */\n-\t\t\ttotal_len += strlen(ref_rev_parse_rules[nr_rules]) - 2 + 1;\n-\n-\t\tscanf_fmts = xmalloc(nr_rules * sizeof(char *) + total_len);\n-\n-\t\toffset = 0;\n-\t\tfor (i = 0; i < nr_rules; i++) {\n-\t\t\tassert(offset < total_len);\n-\t\t\tscanf_fmts[i] = (char *)&scanf_fmts[nr_rules] + offset;\n-\t\t\toffset += snprintf(scanf_fmts[i], total_len - offset,\n-\t\t\t\t\t   ref_rev_parse_rules[i], 2, \"%s\") + 1;\n-\t\t}\n-\t}\n-\n-\t/* bail out if there are no rules */\n-\tif (!nr_rules)\n-\t\treturn xstrdup(refname);\n-\n-\t/* buffer for scanf result, at most refname must fit */\n-\tshort_name = xstrdup(refname);\n-\n-\t/* skip first rule, it will always match */\n-\tfor (i = nr_rules - 1; i > 0 ; --i) {\n-\t\tint j;\n-\t\tint rules_to_fail = i;\n-\t\tint short_name_len;\n-\n-\t\tif (1 != sscanf(refname, scanf_fmts[i], short_name))\n-\t\t\tcontinue;\n-\n-\t\tshort_name_len = strlen(short_name);\n-\n-\t\t/*\n-\t\t * in strict mode, all (except the matched one) rules\n-\t\t * must fail to resolve to a valid non-ambiguous ref\n-\t\t */\n-\t\tif (strict)\n-\t\t\trules_to_fail = nr_rules;\n-\n-\t\t/*\n-\t\t * check if the short name resolves to a valid ref,\n-\t\t * but use only rules prior to the matched one\n-\t\t */\n-\t\tfor (j = 0; j < rules_to_fail; j++) {\n-\t\t\tconst char *rule = ref_rev_parse_rules[j];\n-\t\t\tchar refname[PATH_MAX];\n-\n-\t\t\t/* skip matched rule */\n-\t\t\tif (i == j)\n-\t\t\t\tcontinue;\n-\n-\t\t\t/*\n-\t\t\t * the short name is ambiguous, if it resolves\n-\t\t\t * (with this previous rule) to a valid ref\n-\t\t\t * read_ref() returns 0 on success\n-\t\t\t */\n-\t\t\tmksnpath(refname, sizeof(refname),\n-\t\t\t\t rule, short_name_len, short_name);\n-\t\t\tif (ref_exists(refname))\n-\t\t\t\tbreak;\n-\t\t}\n-\n-\t\t/*\n-\t\t * short name is non-ambiguous if all previous rules\n-\t\t * haven't resolved to a valid ref\n-\t\t */\n-\t\tif (j == rules_to_fail)\n-\t\t\treturn short_name;\n-\t}\n-\n-\tfree(short_name);\n-\treturn xstrdup(refname);\n-}\ndiff --git a/refs.c b/refs.c\nindex 9e2059b..adf0c29 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -295,3 +295,205 @@ int ref_is_hidden(const char *refname)\n \t}\n \treturn 0;\n }\n+\n+static const char *ref_rev_parse_rules[] = {\n+\t\"%.*s\",\n+\t\"refs/%.*s\",\n+\t\"refs/tags/%.*s\",\n+\t\"refs/heads/%.*s\",\n+\t\"refs/remotes/%.*s\",\n+\t\"refs/remotes/%.*s/HEAD\",\n+\tNULL\n+};\n+\n+int refname_match(const char *abbrev_name, const char *full_name)\n+{\n+\tconst char **p;\n+\tconst int abbrev_name_len = strlen(abbrev_name);\n+\n+\tfor (p = ref_rev_parse_rules; *p; p++) {\n+\t\tif (!strcmp(full_name, mkpath(*p, abbrev_name_len, abbrev_name))) {\n+\t\t\treturn 1;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * *string and *len will only be substituted, and *string returned (for\n+ * later free()ing) if the string passed in is a magic short-hand form\n+ * to name a branch.\n+ */\n+static char *substitute_branch_name(const char **string, int *len)\n+{\n+\tstruct strbuf buf = STRBUF_INIT;\n+\tint ret = interpret_branch_name(*string, *len, &buf);\n+\n+\tif (ret == *len) {\n+\t\tsize_t size;\n+\t\t*string = strbuf_detach(&buf, &size);\n+\t\t*len = size;\n+\t\treturn (char *)*string;\n+\t}\n+\n+\treturn NULL;\n+}\n+\n+int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)\n+{\n+\tchar *last_branch = substitute_branch_name(&str, &len);\n+\tconst char **p, *r;\n+\tint refs_found = 0;\n+\n+\t*ref = NULL;\n+\tfor (p = ref_rev_parse_rules; *p; p++) {\n+\t\tchar fullref[PATH_MAX];\n+\t\tunsigned char sha1_from_ref[20];\n+\t\tunsigned char *this_result;\n+\t\tint flag;\n+\n+\t\tthis_result = refs_found ? sha1_from_ref : sha1;\n+\t\tmksnpath(fullref, sizeof(fullref), *p, len, str);\n+\t\tr = resolve_ref_unsafe(fullref, this_result,\n+\t\t\t\t       RESOLVE_REF_READING, &flag);\n+\t\tif (r) {\n+\t\t\tif (!refs_found++)\n+\t\t\t\t*ref = xstrdup(r);\n+\t\t\tif (!warn_ambiguous_refs)\n+\t\t\t\tbreak;\n+\t\t} else if ((flag & REF_ISSYMREF) && strcmp(fullref, \"HEAD\")) {\n+\t\t\twarning(\"ignoring dangling symref %s.\", fullref);\n+\t\t} else if ((flag & REF_ISBROKEN) && strchr(fullref, '/')) {\n+\t\t\twarning(\"ignoring broken ref %s.\", fullref);\n+\t\t}\n+\t}\n+\tfree(last_branch);\n+\treturn refs_found;\n+}\n+\n+int dwim_log(const char *str, int len, unsigned char *sha1, char **log)\n+{\n+\tchar *last_branch = substitute_branch_name(&str, &len);\n+\tconst char **p;\n+\tint logs_found = 0;\n+\n+\t*log = NULL;\n+\tfor (p = ref_rev_parse_rules; *p; p++) {\n+\t\tunsigned char hash[20];\n+\t\tchar path[PATH_MAX];\n+\t\tconst char *ref, *it;\n+\n+\t\tmksnpath(path, sizeof(path), *p, len, str);\n+\t\tref = resolve_ref_unsafe(path, hash, RESOLVE_REF_READING, NULL);\n+\t\tif (!ref)\n+\t\t\tcontinue;\n+\t\tif (reflog_exists(path))\n+\t\t\tit = path;\n+\t\telse if (strcmp(ref, path) && reflog_exists(ref))\n+\t\t\tit = ref;\n+\t\telse\n+\t\t\tcontinue;\n+\t\tif (!logs_found++) {\n+\t\t\t*log = xstrdup(it);\n+\t\t\thashcpy(sha1, hash);\n+\t\t}\n+\t\tif (!warn_ambiguous_refs)\n+\t\t\tbreak;\n+\t}\n+\tfree(last_branch);\n+\treturn logs_found;\n+}\n+\n+char *shorten_unambiguous_ref(const char *refname, int strict)\n+{\n+\tint i;\n+\tstatic char **scanf_fmts;\n+\tstatic int nr_rules;\n+\tchar *short_name;\n+\n+\tif (!nr_rules) {\n+\t\t/*\n+\t\t * Pre-generate scanf formats from ref_rev_parse_rules[].\n+\t\t * Generate a format suitable for scanf from a\n+\t\t * ref_rev_parse_rules rule by interpolating \"%s\" at the\n+\t\t * location of the \"%.*s\".\n+\t\t */\n+\t\tsize_t total_len = 0;\n+\t\tsize_t offset = 0;\n+\n+\t\t/* the rule list is NULL terminated, count them first */\n+\t\tfor (nr_rules = 0; ref_rev_parse_rules[nr_rules]; nr_rules++)\n+\t\t\t/* -2 for strlen(\"%.*s\") - strlen(\"%s\"); +1 for NUL */\n+\t\t\ttotal_len += strlen(ref_rev_parse_rules[nr_rules]) - 2 + 1;\n+\n+\t\tscanf_fmts = xmalloc(nr_rules * sizeof(char *) + total_len);\n+\n+\t\toffset = 0;\n+\t\tfor (i = 0; i < nr_rules; i++) {\n+\t\t\tassert(offset < total_len);\n+\t\t\tscanf_fmts[i] = (char *)&scanf_fmts[nr_rules] + offset;\n+\t\t\toffset += snprintf(scanf_fmts[i], total_len - offset,\n+\t\t\t\t\t   ref_rev_parse_rules[i], 2, \"%s\") + 1;\n+\t\t}\n+\t}\n+\n+\t/* bail out if there are no rules */\n+\tif (!nr_rules)\n+\t\treturn xstrdup(refname);\n+\n+\t/* buffer for scanf result, at most refname must fit */\n+\tshort_name = xstrdup(refname);\n+\n+\t/* skip first rule, it will always match */\n+\tfor (i = nr_rules - 1; i > 0 ; --i) {\n+\t\tint j;\n+\t\tint rules_to_fail = i;\n+\t\tint short_name_len;\n+\n+\t\tif (1 != sscanf(refname, scanf_fmts[i], short_name))\n+\t\t\tcontinue;\n+\n+\t\tshort_name_len = strlen(short_name);\n+\n+\t\t/*\n+\t\t * in strict mode, all (except the matched one) rules\n+\t\t * must fail to resolve to a valid non-ambiguous ref\n+\t\t */\n+\t\tif (strict)\n+\t\t\trules_to_fail = nr_rules;\n+\n+\t\t/*\n+\t\t * check if the short name resolves to a valid ref,\n+\t\t * but use only rules prior to the matched one\n+\t\t */\n+\t\tfor (j = 0; j < rules_to_fail; j++) {\n+\t\t\tconst char *rule = ref_rev_parse_rules[j];\n+\t\t\tchar refname[PATH_MAX];\n+\n+\t\t\t/* skip matched rule */\n+\t\t\tif (i == j)\n+\t\t\t\tcontinue;\n+\n+\t\t\t/*\n+\t\t\t * the short name is ambiguous, if it resolves\n+\t\t\t * (with this previous rule) to a valid ref\n+\t\t\t * read_ref() returns 0 on success\n+\t\t\t */\n+\t\t\tmksnpath(refname, sizeof(refname),\n+\t\t\t\t rule, short_name_len, short_name);\n+\t\t\tif (ref_exists(refname))\n+\t\t\t\tbreak;\n+\t\t}\n+\n+\t\t/*\n+\t\t * short name is non-ambiguous if all previous rules\n+\t\t * haven't resolved to a valid ref\n+\t\t */\n+\t\tif (j == rules_to_fail)\n+\t\t\treturn short_name;\n+\t}\n+\n+\tfree(short_name);\n+\treturn xstrdup(refname);\n+}\n-- \n2.0.1.552.g1af257a\n"},{"id":"247939","messageId":"1408465847-30384-11-git-send-email-sahlberg@google.com","threadId":"37379","inReplyTo":"1408465847-30384-1-git-send-email-sahlberg@google.com","subject":"[PATCH v3 10/23] refs.c: move warn_if_dangling_symref* to the common code","fromName":"Ronnie Sahlberg","fromEmail":"sahlberg@google.com","sentAt":"2014-08-19T16:30:34Z","receivedAt":"2014-08-19T16:30:34Z","isPatch":true,"sender":{"key":"sahlberg@google.com","avatar":"https://avatars.githubusercontent.com/u/7320636?v=4"},"body":"These functions do not use any backend specific code so we can move\nthem to the common code.\n\nSigned-off-by: Ronnie Sahlberg <sahlberg@google.com>\n---\n refs-be-files.c | 52 ----------------------------------------------------\n refs.c          | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 52 insertions(+), 52 deletions(-)\n\ndiff --git a/refs-be-files.c b/refs-be-files.c\nindex 56e146f..40c329b 100644\n--- a/refs-be-files.c\n+++ b/refs-be-files.c\n@@ -1667,58 +1667,6 @@ int peel_ref(const char *refname, unsigned char *sha1)\n \treturn peel_object(base, sha1);\n }\n \n-struct warn_if_dangling_data {\n-\tFILE *fp;\n-\tconst char *refname;\n-\tconst struct string_list *refnames;\n-\tconst char *msg_fmt;\n-};\n-\n-static int warn_if_dangling_symref(const char *refname, const unsigned char *sha1,\n-\t\t\t\t   int flags, void *cb_data)\n-{\n-\tstruct warn_if_dangling_data *d = cb_data;\n-\tconst char *resolves_to;\n-\tunsigned char junk[20];\n-\n-\tif (!(flags & REF_ISSYMREF))\n-\t\treturn 0;\n-\n-\tresolves_to = resolve_ref_unsafe(refname, junk, 0, NULL);\n-\tif (!resolves_to\n-\t    || (d->refname\n-\t\t? strcmp(resolves_to, d->refname)\n-\t\t: !string_list_has_string(d->refnames, resolves_to))) {\n-\t\treturn 0;\n-\t}\n-\n-\tfprintf(d->fp, d->msg_fmt, refname);\n-\tfputc('\\n', d->fp);\n-\treturn 0;\n-}\n-\n-void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname)\n-{\n-\tstruct warn_if_dangling_data data;\n-\n-\tdata.fp = fp;\n-\tdata.refname = refname;\n-\tdata.refnames = NULL;\n-\tdata.msg_fmt = msg_fmt;\n-\tfor_each_rawref(warn_if_dangling_symref, &data);\n-}\n-\n-void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, const struct string_list *refnames)\n-{\n-\tstruct warn_if_dangling_data data;\n-\n-\tdata.fp = fp;\n-\tdata.refname = NULL;\n-\tdata.refnames = refnames;\n-\tdata.msg_fmt = msg_fmt;\n-\tfor_each_rawref(warn_if_dangling_symref, &data);\n-}\n-\n /*\n  * Call fn for each reference in the specified ref_cache, omitting\n  * references not in the containing_dir of base.  fn is called for all\ndiff --git a/refs.c b/refs.c\nindex adf0c29..3011452 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -497,3 +497,55 @@ char *shorten_unambiguous_ref(const char *refname, int strict)\n \tfree(short_name);\n \treturn xstrdup(refname);\n }\n+\n+struct warn_if_dangling_data {\n+\tFILE *fp;\n+\tconst char *refname;\n+\tconst struct string_list *refnames;\n+\tconst char *msg_fmt;\n+};\n+\n+static int warn_if_dangling_symref(const char *refname, const unsigned char *sha1,\n+\t\t\t\t   int flags, void *cb_data)\n+{\n+\tstruct warn_if_dangling_data *d = cb_data;\n+\tconst char *resolves_to;\n+\tunsigned char junk[20];\n+\n+\tif (!(flags & REF_ISSYMREF))\n+\t\treturn 0;\n+\n+\tresolves_to = resolve_ref_unsafe(refname, junk, 0, NULL);\n+\tif (!resolves_to\n+\t    || (d->refname\n+\t\t? strcmp(resolves_to, d->refname)\n+\t\t: !string_list_has_string(d->refnames, resolves_to))) {\n+\t\treturn 0;\n+\t}\n+\n+\tfprintf(d->fp, d->msg_fmt, refname);\n+\tfputc('\\n', d->fp);\n+\treturn 0;\n+}\n+\n+void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname)\n+{\n+\tstruct warn_if_dangling_data data;\n+\n+\tdata.fp = fp;\n+\tdata.refname = refname;\n+\tdata.refnames = NULL;\n+\tdata.msg_fmt = msg_fmt;\n+\tfor_each_rawref(warn_if_dangling_symref, &data);\n+}\n+\n+void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, const struct string_list *refnames)\n+{\n+\tstruct warn_if_dangling_data data;\n+\n+\tdata.fp = fp;\n+\tdata.refname = NULL;\n+\tdata.refnames = refnames;\n+\tdata.msg_fmt = msg_fmt;\n+\tfor_each_rawref(warn_if_dangling_symref, &data);\n+}\n-- \n2.0.1.552.g1af257a\n"},{"id":"247940","messageId":"1408465847-30384-12-git-send-email-sahlberg@google.com","threadId":"37379","inReplyTo":"1408465847-30384-1-git-send-email-sahlberg@google.com","subject":"[PATCH v3 11/23] refs.c: move read_ref, read_ref_full and ref_exists to the common code","fromName":"Ronnie Sahlberg","fromEmail":"sahlberg@google.com","sentAt":"2014-08-19T16:30:35Z","receivedAt":"2014-08-19T16:30:35Z","isPatch":true,"sender":{"key":"sahlberg@google.com","avatar":"https://avatars.githubusercontent.com/u/7320636?v=4"},"body":"These functions do not depend on the backend implementation so we\ncan move them to the common code.\n\nSigned-off-by: Ronnie Sahlberg <sahlberg@google.com>\n---\n refs-be-files.c | 18 ------------------\n refs.c          | 18 ++++++++++++++++++\n 2 files changed, 18 insertions(+), 18 deletions(-)\n\ndiff --git a/refs-be-files.c b/refs-be-files.c\nindex 40c329b..a94378e 100644\n--- a/refs-be-files.c\n+++ b/refs-be-files.c\n@@ -1514,24 +1514,6 @@ struct ref_filter {\n \tvoid *cb_data;\n };\n \n-int read_ref_full(const char *refname, unsigned char *sha1, int flags, int *ref_flag)\n-{\n-\tif (resolve_ref_unsafe(refname, sha1, flags, ref_flag))\n-\t\treturn 0;\n-\treturn -1;\n-}\n-\n-int read_ref(const char *refname, unsigned char *sha1)\n-{\n-\treturn read_ref_full(refname, sha1, RESOLVE_REF_READING, NULL);\n-}\n-\n-int ref_exists(const char *refname)\n-{\n-\tunsigned char sha1[20];\n-\treturn !!resolve_ref_unsafe(refname, sha1, RESOLVE_REF_READING, NULL);\n-}\n-\n static int filter_refs(const char *refname, const unsigned char *sha1, int flags,\n \t\t       void *data)\n {\ndiff --git a/refs.c b/refs.c\nindex 3011452..a0e6d81 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -549,3 +549,21 @@ void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, const struct string_li\n \tdata.msg_fmt = msg_fmt;\n \tfor_each_rawref(warn_if_dangling_symref, &data);\n }\n+\n+int read_ref_full(const char *refname, unsigned char *sha1, int flags, int *ref_flag)\n+{\n+\tif (resolve_ref_unsafe(refname, sha1, flags, ref_flag))\n+\t\treturn 0;\n+\treturn -1;\n+}\n+\n+int read_ref(const char *refname, unsigned char *sha1)\n+{\n+\treturn read_ref_full(refname, sha1, RESOLVE_REF_READING, NULL);\n+}\n+\n+int ref_exists(const char *refname)\n+{\n+\tunsigned char sha1[20];\n+\treturn !!resolve_ref_unsafe(refname, sha1, RESOLVE_REF_READING, NULL);\n+}\n-- \n2.0.1.552.g1af257a\n"},{"id":"247931","messageId":"1408465847-30384-13-git-send-email-sahlberg@google.com","threadId":"37379","inReplyTo":"1408465847-30384-1-git-send-email-sahlberg@google.com","subject":"[PATCH v3 12/23] refs.c: move resolve_refdup to common","fromName":"Ronnie Sahlberg","fromEmail":"sahlberg@google.com","sentAt":"2014-08-19T16:30:36Z","receivedAt":"2014-08-19T16:30:36Z","isPatch":true,"sender":{"key":"sahlberg@google.com","avatar":"https://avatars.githubusercontent.com/u/7320636?v=4"},"body":"This function can be shared across all refs backends so move it\nto the common code.\n\nSigned-off-by: Ronnie Sahlberg <sahlberg@google.com>\n---\n refs-be-files.c | 6 ------\n refs.c          | 6 ++++++\n 2 files changed, 6 insertions(+), 6 deletions(-)\n\ndiff --git a/refs-be-files.c b/refs-be-files.c\nindex a94378e..ed7bc61 100644\n--- a/refs-be-files.c\n+++ b/refs-be-files.c\n@@ -1501,12 +1501,6 @@ const char *resolve_ref_unsafe(const char *refname, unsigned char *sha1, int fla\n \t}\n }\n \n-char *resolve_refdup(const char *ref, unsigned char *sha1, int flags, int *ref_flag)\n-{\n-\tconst char *ret = resolve_ref_unsafe(ref, sha1, flags, ref_flag);\n-\treturn ret ? xstrdup(ret) : NULL;\n-}\n-\n /* The argument to filter_refs */\n struct ref_filter {\n \tconst char *pattern;\ndiff --git a/refs.c b/refs.c\nindex a0e6d81..b8582f8 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -567,3 +567,9 @@ int ref_exists(const char *refname)\n \tunsigned char sha1[20];\n \treturn !!resolve_ref_unsafe(refname, sha1, RESOLVE_REF_READING, NULL);\n }\n+\n+char *resolve_refdup(const char *ref, unsigned char *sha1, int flags, int *ref_flag)\n+{\n+\tconst char *ret = resolve_ref_unsafe(ref, sha1, flags, ref_flag);\n+\treturn ret ? xstrdup(ret) : NULL;\n+}\n-- \n2.0.1.552.g1af257a\n"},{"id":"247937","messageId":"1408465847-30384-14-git-send-email-sahlberg@google.com","threadId":"37379","inReplyTo":"1408465847-30384-1-git-send-email-sahlberg@google.com","subject":"[PATCH v3 13/23] refs.c: move check_refname_component to the common code","fromName":"Ronnie Sahlberg","fromEmail":"sahlberg@google.com","sentAt":"2014-08-19T16:30:37Z","receivedAt":"2014-08-19T16:30:37Z","isPatch":true,"sender":{"key":"sahlberg@google.com","avatar":"https://avatars.githubusercontent.com/u/7320636?v=4"},"body":"This function does not contain any backend specific code so we\ncan move it to the common code.\n\nSigned-off-by: Ronnie Sahlberg <sahlberg@google.com>\n---\n refs-be-files.c | 110 --------------------------------------------------------\n refs.c          | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 110 insertions(+), 110 deletions(-)\n\ndiff --git a/refs-be-files.c b/refs-be-files.c\nindex ed7bc61..55bced9 100644\n--- a/refs-be-files.c\n+++ b/refs-be-files.c\n@@ -6,25 +6,6 @@\n #include \"string-list.h\"\n \n /*\n- * How to handle various characters in refnames:\n- * 0: An acceptable character for refs\n- * 1: End-of-component\n- * 2: ., look for a preceding . to reject .. in refs\n- * 3: {, look for a preceding @ to reject @{ in refs\n- * 4: A bad character: ASCII control characters, \"~\", \"^\", \":\" or SP\n- */\n-static unsigned char refname_disposition[256] = {\n-\t1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n-\t4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n-\t4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 2, 1,\n-\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 4,\n-\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n-\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 4, 0,\n-\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n-\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 4, 4\n-};\n-\n-/*\n  * Used as a flag to transaction_delete_sha1 when a loose ref is being\n  * pruned.\n  */\n@@ -35,97 +16,6 @@ static unsigned char refname_disposition[256] = {\n  */\n #define UPDATE_REFLOG_NOLOCK 0x0200\n \n-/*\n- * Try to read one refname component from the front of refname.\n- * Return the length of the component found, or -1 if the component is\n- * not legal.  It is legal if it is something reasonable to have under\n- * \".git/refs/\"; We do not like it if:\n- *\n- * - any path component of it begins with \".\", or\n- * - it has double dots \"..\", or\n- * - it has ASCII control character, \"~\", \"^\", \":\" or SP, anywhere, or\n- * - it ends with a \"/\".\n- * - it ends with \".lock\"\n- * - it contains a \"\\\" (backslash)\n- */\n-static int check_refname_component(const char *refname, int flags)\n-{\n-\tconst char *cp;\n-\tchar last = '\\0';\n-\n-\tfor (cp = refname; ; cp++) {\n-\t\tint ch = *cp & 255;\n-\t\tunsigned char disp = refname_disposition[ch];\n-\t\tswitch (disp) {\n-\t\tcase 1:\n-\t\t\tgoto out;\n-\t\tcase 2:\n-\t\t\tif (last == '.')\n-\t\t\t\treturn -1; /* Refname contains \"..\". */\n-\t\t\tbreak;\n-\t\tcase 3:\n-\t\t\tif (last == '@')\n-\t\t\t\treturn -1; /* Refname contains \"@{\". */\n-\t\t\tbreak;\n-\t\tcase 4:\n-\t\t\treturn -1;\n-\t\t}\n-\t\tlast = ch;\n-\t}\n-out:\n-\tif (cp == refname)\n-\t\treturn 0; /* Component has zero length. */\n-\tif (refname[0] == '.') {\n-\t\tif (!(flags & REFNAME_DOT_COMPONENT))\n-\t\t\treturn -1; /* Component starts with '.'. */\n-\t\t/*\n-\t\t * Even if leading dots are allowed, don't allow \".\"\n-\t\t * as a component (\"..\" is prevented by a rule above).\n-\t\t */\n-\t\tif (refname[1] == '\\0')\n-\t\t\treturn -1; /* Component equals \".\". */\n-\t}\n-\tif (cp - refname >= 5 && !memcmp(cp - 5, \".lock\", 5))\n-\t\treturn -1; /* Refname ends with \".lock\". */\n-\treturn cp - refname;\n-}\n-\n-int check_refname_format(const char *refname, int flags)\n-{\n-\tint component_len, component_count = 0;\n-\n-\tif (!strcmp(refname, \"@\"))\n-\t\t/* Refname is a single character '@'. */\n-\t\treturn -1;\n-\n-\twhile (1) {\n-\t\t/* We are at the start of a path component. */\n-\t\tcomponent_len = check_refname_component(refname, flags);\n-\t\tif (component_len <= 0) {\n-\t\t\tif ((flags & REFNAME_REFSPEC_PATTERN) &&\n-\t\t\t\t\trefname[0] == '*' &&\n-\t\t\t\t\t(refname[1] == '\\0' || refname[1] == '/')) {\n-\t\t\t\t/* Accept one wildcard as a full refname component. */\n-\t\t\t\tflags &= ~REFNAME_REFSPEC_PATTERN;\n-\t\t\t\tcomponent_len = 1;\n-\t\t\t} else {\n-\t\t\t\treturn -1;\n-\t\t\t}\n-\t\t}\n-\t\tcomponent_count++;\n-\t\tif (refname[component_len] == '\\0')\n-\t\t\tbreak;\n-\t\t/* Skip to next component. */\n-\t\trefname += component_len + 1;\n-\t}\n-\n-\tif (refname[component_len - 1] == '.')\n-\t\treturn -1; /* Refname ends with '.'. */\n-\tif (!(flags & REFNAME_ALLOW_ONELEVEL) && component_count < 2)\n-\t\treturn -1; /* Refname has only one component. */\n-\treturn 0;\n-}\n-\n struct ref_entry;\n \n /*\ndiff --git a/refs.c b/refs.c\nindex b8582f8..ea5f276 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -573,3 +573,113 @@ char *resolve_refdup(const char *ref, unsigned char *sha1, int flags, int *ref_f\n \tconst char *ret = resolve_ref_unsafe(ref, sha1, flags, ref_flag);\n \treturn ret ? xstrdup(ret) : NULL;\n }\n+\n+/*\n+ * How to handle various characters in refnames:\n+ * 0: An acceptable character for refs\n+ * 1: End-of-component\n+ * 2: ., look for a preceding . to reject .. in refs\n+ * 3: {, look for a preceding @ to reject @{ in refs\n+ * 4: A bad character: ASCII control characters, \"~\", \"^\", \":\" or SP\n+ */\n+static unsigned char refname_disposition[256] = {\n+\t1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n+\t4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n+\t4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 2, 1,\n+\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 4,\n+\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n+\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 4, 0,\n+\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n+\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 4, 4\n+};\n+\n+/*\n+ * Try to read one refname component from the front of refname.\n+ * Return the length of the component found, or -1 if the component is\n+ * not legal.  It is legal if it is something reasonable to have under\n+ * \".git/refs/\"; We do not like it if:\n+ *\n+ * - any path component of it begins with \".\", or\n+ * - it has double dots \"..\", or\n+ * - it has ASCII control character, \"~\", \"^\", \":\" or SP, anywhere, or\n+ * - it ends with a \"/\".\n+ * - it ends with \".lock\"\n+ * - it contains a \"\\\" (backslash)\n+ */\n+static int check_refname_component(const char *refname, int flags)\n+{\n+\tconst char *cp;\n+\tchar last = '\\0';\n+\n+\tfor (cp = refname; ; cp++) {\n+\t\tint ch = *cp & 255;\n+\t\tunsigned char disp = refname_disposition[ch];\n+\t\tswitch (disp) {\n+\t\tcase 1:\n+\t\t\tgoto out;\n+\t\tcase 2:\n+\t\t\tif (last == '.')\n+\t\t\t\treturn -1; /* Refname contains \"..\". */\n+\t\t\tbreak;\n+\t\tcase 3:\n+\t\t\tif (last == '@')\n+\t\t\t\treturn -1; /* Refname contains \"@{\". */\n+\t\t\tbreak;\n+\t\tcase 4:\n+\t\t\treturn -1;\n+\t\t}\n+\t\tlast = ch;\n+\t}\n+out:\n+\tif (cp == refname)\n+\t\treturn 0; /* Component has zero length. */\n+\tif (refname[0] == '.') {\n+\t\tif (!(flags & REFNAME_DOT_COMPONENT))\n+\t\t\treturn -1; /* Component starts with '.'. */\n+\t\t/*\n+\t\t * Even if leading dots are allowed, don't allow \".\"\n+\t\t * as a component (\"..\" is prevented by a rule above).\n+\t\t */\n+\t\tif (refname[1] == '\\0')\n+\t\t\treturn -1; /* Component equals \".\". */\n+\t}\n+\tif (cp - refname >= 5 && !memcmp(cp - 5, \".lock\", 5))\n+\t\treturn -1; /* Refname ends with \".lock\". */\n+\treturn cp - refname;\n+}\n+\n+int check_refname_format(const char *refname, int flags)\n+{\n+\tint component_len, component_count = 0;\n+\n+\tif (!strcmp(refname, \"@\"))\n+\t\t/* Refname is a single character '@'. */\n+\t\treturn -1;\n+\n+\twhile (1) {\n+\t\t/* We are at the start of a path component. */\n+\t\tcomponent_len = check_refname_component(refname, flags);\n+\t\tif (component_len <= 0) {\n+\t\t\tif ((flags & REFNAME_REFSPEC_PATTERN) &&\n+\t\t\t\t\trefname[0] == '*' &&\n+\t\t\t\t\t(refname[1] == '\\0' || refname[1] == '/')) {\n+\t\t\t\t/* Accept one wildcard as a full refname component. */\n+\t\t\t\tflags &= ~REFNAME_REFSPEC_PATTERN;\n+\t\t\t\tcomponent_len = 1;\n+\t\t\t} else {\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t}\n+\t\tcomponent_count++;\n+\t\tif (refname[component_len] == '\\0')\n+\t\t\tbreak;\n+\t\t/* Skip to next component. */\n+\t\trefname += component_len + 1;\n+\t}\n+\n+\tif (refname[component_len - 1] == '.')\n+\t\treturn -1; /* Refname ends with '.'. */\n+\tif (!(flags & REFNAME_ALLOW_ONELEVEL) && component_count < 2)\n+\t\treturn -1; /* Refname has only one component. */\n+\treturn 0;\n+}\n-- \n2.0.1.552.g1af257a\n"},{"id":"247945","messageId":"1408465847-30384-15-git-send-email-sahlberg@google.com","threadId":"37379","inReplyTo":"1408465847-30384-1-git-send-email-sahlberg@google.com","subject":"[PATCH v3 14/23] refs.c: move is_branch to the common code","fromName":"Ronnie Sahlberg","fromEmail":"sahlberg@google.com","sentAt":"2014-08-19T16:30:38Z","receivedAt":"2014-08-19T16:30:38Z","isPatch":true,"sender":{"key":"sahlberg@google.com","avatar":"https://avatars.githubusercontent.com/u/7320636?v=4"},"body":"Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>\n---\n refs-be-files.c | 5 -----\n refs.c          | 5 +++++\n 2 files changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/refs-be-files.c b/refs-be-files.c\nindex 55bced9..70c034c 100644\n--- a/refs-be-files.c\n+++ b/refs-be-files.c\n@@ -2483,11 +2483,6 @@ static int log_ref_write(const char *refname, const unsigned char *old_sha1,\n \treturn 0;\n }\n \n-int is_branch(const char *refname)\n-{\n-\treturn !strcmp(refname, \"HEAD\") || starts_with(refname, \"refs/heads/\");\n-}\n-\n static int write_sha1_update_reflog(struct ref_lock *lock,\n \tconst unsigned char *sha1, const char *logmsg)\n {\ndiff --git a/refs.c b/refs.c\nindex ea5f276..9bc0a31 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -683,3 +683,8 @@ int check_refname_format(const char *refname, int flags)\n \t\treturn -1; /* Refname has only one component. */\n \treturn 0;\n }\n+\n+int is_branch(const char *refname)\n+{\n+\treturn !strcmp(refname, \"HEAD\") || starts_with(refname, \"refs/heads/\");\n+}\n-- \n2.0.1.552.g1af257a\n"},{"id":"247930","messageId":"1408465847-30384-16-git-send-email-sahlberg@google.com","threadId":"37379","inReplyTo":"1408465847-30384-1-git-send-email-sahlberg@google.com","subject":"[PATCH v3 15/23] refs.c: move names_conflict to the common code","fromName":"Ronnie Sahlberg","fromEmail":"sahlberg@google.com","sentAt":"2014-08-19T16:30:39Z","receivedAt":"2014-08-19T16:30:39Z","isPatch":true,"sender":{"key":"sahlberg@google.com","avatar":"https://avatars.githubusercontent.com/u/7320636?v=4"},"body":"Move names_conflict to the common code and make it public.\nWe want to use the same name conflict checks across all backends\nso we guarantee compatibility across backends.\n\nSigned-off-by: Ronnie Sahlberg <sahlberg@google.com>\n---\n refs-be-files.c | 14 --------------\n refs.c          |  8 ++++++++\n refs.h          |  9 +++++++++\n 3 files changed, 17 insertions(+), 14 deletions(-)\n\ndiff --git a/refs-be-files.c b/refs-be-files.c\nindex 70c034c..6542969 100644\n--- a/refs-be-files.c\n+++ b/refs-be-files.c\n@@ -676,20 +676,6 @@ static void prime_ref_dir(struct ref_dir *dir)\n \t\t\tprime_ref_dir(get_ref_dir(entry));\n \t}\n }\n-/*\n- * Return true iff refname1 and refname2 conflict with each other.\n- * Two reference names conflict if one of them exactly matches the\n- * leading components of the other; e.g., \"foo/bar\" conflicts with\n- * both \"foo\" and with \"foo/bar/baz\" but not with \"foo/bar\" or\n- * \"foo/barbados\".\n- */\n-static int names_conflict(const char *refname1, const char *refname2)\n-{\n-\tfor (; *refname1 && *refname1 == *refname2; refname1++, refname2++)\n-\t\t;\n-\treturn (*refname1 == '\\0' && *refname2 == '/')\n-\t\t|| (*refname1 == '/' && *refname2 == '\\0');\n-}\n \n struct name_conflict_cb {\n \tconst char *refname;\ndiff --git a/refs.c b/refs.c\nindex 9bc0a31..177bed6 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -688,3 +688,11 @@ int is_branch(const char *refname)\n {\n \treturn !strcmp(refname, \"HEAD\") || starts_with(refname, \"refs/heads/\");\n }\n+\n+int names_conflict(const char *refname1, const char *refname2)\n+{\n+\tfor (; *refname1 && *refname1 == *refname2; refname1++, refname2++)\n+\t\t;\n+\treturn (*refname1 == '\\0' && *refname2 == '/')\n+\t\t|| (*refname1 == '/' && *refname2 == '\\0');\n+}\ndiff --git a/refs.h b/refs.h\nindex d526da0..a14fc5d 100644\n--- a/refs.h\n+++ b/refs.h\n@@ -128,6 +128,15 @@ int pack_refs(unsigned int flags, struct strbuf *err);\n \n extern int ref_exists(const char *);\n \n+/*\n+ * Return true iff refname1 and refname2 conflict with each other.\n+ * Two reference names conflict if one of them exactly matches the\n+ * leading components of the other; e.g., \"foo/bar\" conflicts with\n+ * both \"foo\" and with \"foo/bar/baz\" but not with \"foo/bar\" or\n+ * \"foo/barbados\".\n+ */\n+int names_conflict(const char *refname1, const char *refname2);\n+\n extern int is_branch(const char *refname);\n \n /*\n-- \n2.0.1.552.g1af257a\n"},{"id":"247932","messageId":"1408465847-30384-17-git-send-email-sahlberg@google.com","threadId":"37379","inReplyTo":"1408465847-30384-1-git-send-email-sahlberg@google.com","subject":"[PATCH v3 16/23] refs.c: move prettify_refname to the common code","fromName":"Ronnie Sahlberg","fromEmail":"sahlberg@google.com","sentAt":"2014-08-19T16:30:40Z","receivedAt":"2014-08-19T16:30:40Z","isPatch":true,"sender":{"key":"sahlberg@google.com","avatar":"https://avatars.githubusercontent.com/u/7320636?v=4"},"body":"Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>\n---\n refs-be-files.c | 9 ---------\n refs.c          | 9 +++++++++\n 2 files changed, 9 insertions(+), 9 deletions(-)\n\ndiff --git a/refs-be-files.c b/refs-be-files.c\nindex 6542969..fb9c614 100644\n--- a/refs-be-files.c\n+++ b/refs-be-files.c\n@@ -1747,15 +1747,6 @@ int for_each_rawref(each_ref_fn fn, void *cb_data)\n \t\t\t       DO_FOR_EACH_INCLUDE_BROKEN, cb_data);\n }\n \n-const char *prettify_refname(const char *name)\n-{\n-\treturn name + (\n-\t\tstarts_with(name, \"refs/heads/\") ? 11 :\n-\t\tstarts_with(name, \"refs/tags/\") ? 10 :\n-\t\tstarts_with(name, \"refs/remotes/\") ? 13 :\n-\t\t0);\n-}\n-\n static void unlock_ref(struct ref_lock *lock)\n {\n \t/* Do not free lock->lk -- atexit() still looks at them */\ndiff --git a/refs.c b/refs.c\nindex 177bed6..d163e61 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -696,3 +696,12 @@ int names_conflict(const char *refname1, const char *refname2)\n \treturn (*refname1 == '\\0' && *refname2 == '/')\n \t\t|| (*refname1 == '/' && *refname2 == '\\0');\n }\n+\n+const char *prettify_refname(const char *name)\n+{\n+\treturn name + (\n+\t\tstarts_with(name, \"refs/heads/\") ? 11 :\n+\t\tstarts_with(name, \"refs/tags/\") ? 10 :\n+\t\tstarts_with(name, \"refs/remotes/\") ? 13 :\n+\t\t0);\n+}\n-- \n2.0.1.552.g1af257a\n"},{"id":"247947","messageId":"1408465847-30384-18-git-send-email-sahlberg@google.com","threadId":"37379","inReplyTo":"1408465847-30384-1-git-send-email-sahlberg@google.com","subject":"[PATCH v3 17/23] refs.c: move ref iterators to the common code","fromName":"Ronnie Sahlberg","fromEmail":"sahlberg@google.com","sentAt":"2014-08-19T16:30:41Z","receivedAt":"2014-08-19T16:30:41Z","isPatch":true,"sender":{"key":"sahlberg@google.com","avatar":"https://avatars.githubusercontent.com/u/7320636?v=4"},"body":"Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>\n---\n refs-be-files.c | 81 ---------------------------------------------------------\n refs.c          | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 81 insertions(+), 81 deletions(-)\n\ndiff --git a/refs-be-files.c b/refs-be-files.c\nindex fb9c614..9aa88ef 100644\n--- a/refs-be-files.c\n+++ b/refs-be-files.c\n@@ -1377,22 +1377,6 @@ const char *resolve_ref_unsafe(const char *refname, unsigned char *sha1, int fla\n \t}\n }\n \n-/* The argument to filter_refs */\n-struct ref_filter {\n-\tconst char *pattern;\n-\teach_ref_fn *fn;\n-\tvoid *cb_data;\n-};\n-\n-static int filter_refs(const char *refname, const unsigned char *sha1, int flags,\n-\t\t       void *data)\n-{\n-\tstruct ref_filter *filter = (struct ref_filter *)data;\n-\tif (wildmatch(filter->pattern, refname, 0, NULL))\n-\t\treturn 0;\n-\treturn filter->fn(refname, sha1, flags, filter->cb_data);\n-}\n-\n enum peel_status {\n \t/* object was peeled successfully: */\n \tPEEL_PEELED = 0,\n@@ -1646,36 +1630,6 @@ int for_each_ref_in_submodule(const char *submodule, const char *prefix,\n \treturn do_for_each_ref(get_ref_cache(submodule), prefix, fn, strlen(prefix), 0, cb_data);\n }\n \n-int for_each_tag_ref(each_ref_fn fn, void *cb_data)\n-{\n-\treturn for_each_ref_in(\"refs/tags/\", fn, cb_data);\n-}\n-\n-int for_each_tag_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)\n-{\n-\treturn for_each_ref_in_submodule(submodule, \"refs/tags/\", fn, cb_data);\n-}\n-\n-int for_each_branch_ref(each_ref_fn fn, void *cb_data)\n-{\n-\treturn for_each_ref_in(\"refs/heads/\", fn, cb_data);\n-}\n-\n-int for_each_branch_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)\n-{\n-\treturn for_each_ref_in_submodule(submodule, \"refs/heads/\", fn, cb_data);\n-}\n-\n-int for_each_remote_ref(each_ref_fn fn, void *cb_data)\n-{\n-\treturn for_each_ref_in(\"refs/remotes/\", fn, cb_data);\n-}\n-\n-int for_each_remote_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)\n-{\n-\treturn for_each_ref_in_submodule(submodule, \"refs/remotes/\", fn, cb_data);\n-}\n-\n int for_each_replace_ref(each_ref_fn fn, void *cb_data)\n {\n \treturn do_for_each_ref(&ref_cache, \"refs/replace/\", fn, 13, 0, cb_data);\n@@ -1706,41 +1660,6 @@ int for_each_namespaced_ref(each_ref_fn fn, void *cb_data)\n \treturn ret;\n }\n \n-int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,\n-\tconst char *prefix, void *cb_data)\n-{\n-\tstruct strbuf real_pattern = STRBUF_INIT;\n-\tstruct ref_filter filter;\n-\tint ret;\n-\n-\tif (!prefix && !starts_with(pattern, \"refs/\"))\n-\t\tstrbuf_addstr(&real_pattern, \"refs/\");\n-\telse if (prefix)\n-\t\tstrbuf_addstr(&real_pattern, prefix);\n-\tstrbuf_addstr(&real_pattern, pattern);\n-\n-\tif (!has_glob_specials(pattern)) {\n-\t\t/* Append implied '/' '*' if not present. */\n-\t\tif (real_pattern.buf[real_pattern.len - 1] != '/')\n-\t\t\tstrbuf_addch(&real_pattern, '/');\n-\t\t/* No need to check for '*', there is none. */\n-\t\tstrbuf_addch(&real_pattern, '*');\n-\t}\n-\n-\tfilter.pattern = real_pattern.buf;\n-\tfilter.fn = fn;\n-\tfilter.cb_data = cb_data;\n-\tret = for_each_ref(filter_refs, &filter);\n-\n-\tstrbuf_release(&real_pattern);\n-\treturn ret;\n-}\n-\n-int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data)\n-{\n-\treturn for_each_glob_ref_in(fn, pattern, NULL, cb_data);\n-}\n-\n int for_each_rawref(each_ref_fn fn, void *cb_data)\n {\n \treturn do_for_each_ref(&ref_cache, \"\", fn, 0,\ndiff --git a/refs.c b/refs.c\nindex d163e61..964a513 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -705,3 +705,84 @@ const char *prettify_refname(const char *name)\n \t\tstarts_with(name, \"refs/remotes/\") ? 13 :\n \t\t0);\n }\n+\n+/* The argument to filter_refs */\n+struct ref_filter {\n+\tconst char *pattern;\n+\teach_ref_fn *fn;\n+\tvoid *cb_data;\n+};\n+\n+static int filter_refs(const char *refname, const unsigned char *sha1, int flags,\n+\t\t       void *data)\n+{\n+\tstruct ref_filter *filter = (struct ref_filter *)data;\n+\tif (wildmatch(filter->pattern, refname, 0, NULL))\n+\t\treturn 0;\n+\treturn filter->fn(refname, sha1, flags, filter->cb_data);\n+}\n+\n+int for_each_tag_ref(each_ref_fn fn, void *cb_data)\n+{\n+\treturn for_each_ref_in(\"refs/tags/\", fn, cb_data);\n+}\n+\n+int for_each_tag_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)\n+{\n+\treturn for_each_ref_in_submodule(submodule, \"refs/tags/\", fn, cb_data);\n+}\n+\n+int for_each_branch_ref(each_ref_fn fn, void *cb_data)\n+{\n+\treturn for_each_ref_in(\"refs/heads/\", fn, cb_data);\n+}\n+\n+int for_each_branch_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)\n+{\n+\treturn for_each_ref_in_submodule(submodule, \"refs/heads/\", fn, cb_data);\n+}\n+\n+int for_each_remote_ref(each_ref_fn fn, void *cb_data)\n+{\n+\treturn for_each_ref_in(\"refs/remotes/\", fn, cb_data);\n+}\n+\n+int for_each_remote_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)\n+{\n+\treturn for_each_ref_in_submodule(submodule, \"refs/remotes/\", fn, cb_data);\n+}\n+\n+int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,\n+\tconst char *prefix, void *cb_data)\n+{\n+\tstruct strbuf real_pattern = STRBUF_INIT;\n+\tstruct ref_filter filter;\n+\tint ret;\n+\n+\tif (!prefix && !starts_with(pattern, \"refs/\"))\n+\t\tstrbuf_addstr(&real_pattern, \"refs/\");\n+\telse if (prefix)\n+\t\tstrbuf_addstr(&real_pattern, prefix);\n+\tstrbuf_addstr(&real_pattern, pattern);\n+\n+\tif (!has_glob_specials(pattern)) {\n+\t\t/* Append implied '/' '*' if not present. */\n+\t\tif (real_pattern.buf[real_pattern.len - 1] != '/')\n+\t\t\tstrbuf_addch(&real_pattern, '/');\n+\t\t/* No need to check for '*', there is none. */\n+\t\tstrbuf_addch(&real_pattern, '*');\n+\t}\n+\n+\tfilter.pattern = real_pattern.buf;\n+\tfilter.fn = fn;\n+\tfilter.cb_data = cb_data;\n+\tret = for_each_ref(filter_refs, &filter);\n+\n+\tstrbuf_release(&real_pattern);\n+\treturn ret;\n+}\n+\n+int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data)\n+{\n+\treturn for_each_glob_ref_in(fn, pattern, NULL, cb_data);\n+}\n-- \n2.0.1.552.g1af257a\n"},{"id":"247933","messageId":"1408465847-30384-19-git-send-email-sahlberg@google.com","threadId":"37379","inReplyTo":"1408465847-30384-1-git-send-email-sahlberg@google.com","subject":"[PATCH v3 18/23] refs.c: move head_ref_namespaced to the common code","fromName":"Ronnie Sahlberg","fromEmail":"sahlberg@google.com","sentAt":"2014-08-19T16:30:42Z","receivedAt":"2014-08-19T16:30:42Z","isPatch":true,"sender":{"key":"sahlberg@google.com","avatar":"https://avatars.githubusercontent.com/u/7320636?v=4"},"body":"Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>\n---\n refs-be-files.c | 15 ---------------\n refs.c          | 15 +++++++++++++++\n 2 files changed, 15 insertions(+), 15 deletions(-)\n\ndiff --git a/refs-be-files.c b/refs-be-files.c\nindex 9aa88ef..e58a7e1 100644\n--- a/refs-be-files.c\n+++ b/refs-be-files.c\n@@ -1635,21 +1635,6 @@ int for_each_replace_ref(each_ref_fn fn, void *cb_data)\n \treturn do_for_each_ref(&ref_cache, \"refs/replace/\", fn, 13, 0, cb_data);\n }\n \n-int head_ref_namespaced(each_ref_fn fn, void *cb_data)\n-{\n-\tstruct strbuf buf = STRBUF_INIT;\n-\tint ret = 0;\n-\tunsigned char sha1[20];\n-\tint flag;\n-\n-\tstrbuf_addf(&buf, \"%sHEAD\", get_git_namespace());\n-\tif (!read_ref_full(buf.buf, sha1, RESOLVE_REF_READING, &flag))\n-\t\tret = fn(buf.buf, sha1, flag, cb_data);\n-\tstrbuf_release(&buf);\n-\n-\treturn ret;\n-}\n-\n int for_each_namespaced_ref(each_ref_fn fn, void *cb_data)\n {\n \tstruct strbuf buf = STRBUF_INIT;\ndiff --git a/refs.c b/refs.c\nindex 964a513..6b434ad 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -786,3 +786,18 @@ int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data)\n {\n \treturn for_each_glob_ref_in(fn, pattern, NULL, cb_data);\n }\n+\n+int head_ref_namespaced(each_ref_fn fn, void *cb_data)\n+{\n+\tstruct strbuf buf = STRBUF_INIT;\n+\tint ret = 0;\n+\tunsigned char sha1[20];\n+\tint flag;\n+\n+\tstrbuf_addf(&buf, \"%sHEAD\", get_git_namespace());\n+\tif (!read_ref_full(buf.buf, sha1, RESOLVE_REF_READING, &flag))\n+\t\tret = fn(buf.buf, sha1, flag, cb_data);\n+\tstrbuf_release(&buf);\n+\n+\treturn ret;\n+}\n-- \n2.0.1.552.g1af257a\n"},{"id":"247936","messageId":"1408465847-30384-20-git-send-email-sahlberg@google.com","threadId":"37379","inReplyTo":"1408465847-30384-1-git-send-email-sahlberg@google.com","subject":"[PATCH v3 19/23] refs-be-files.c: add a backend method structure with transaction functions","fromName":"Ronnie Sahlberg","fromEmail":"sahlberg@google.com","sentAt":"2014-08-19T16:30:43Z","receivedAt":"2014-08-19T16:30:43Z","isPatch":true,"sender":{"key":"sahlberg@google.com","avatar":"https://avatars.githubusercontent.com/u/7320636?v=4"},"body":"Add a ref structure for backend methods. Start by adding method pointers\nfor the transaction functions.\n\nRename the existing transaction functions to files_* and make them static.\nAdd new transaction functions that just pass through to the appropriate\nmethods for the backend.\n\nSigned-off-by: Ronnie Sahlberg <sahlberg@google.com>\n---\n refs-be-files.c | 68 ++++++++++++++++++++++++++++++++++-----------------------\n refs.c          | 55 ++++++++++++++++++++++++++++++++++++++++++++++\n refs.h          | 35 +++++++++++++++++++++++++++++\n 3 files changed, 131 insertions(+), 27 deletions(-)\n\ndiff --git a/refs-be-files.c b/refs-be-files.c\nindex e58a7e1..27eafd0 100644\n--- a/refs-be-files.c\n+++ b/refs-be-files.c\n@@ -2777,12 +2777,12 @@ struct ref_transaction {\n \tenum ref_transaction_state state;\n };\n \n-struct ref_transaction *transaction_begin(struct strbuf *err)\n+static struct ref_transaction *files_transaction_begin(struct strbuf *err)\n {\n \treturn xcalloc(1, sizeof(struct ref_transaction));\n }\n \n-void transaction_free(struct ref_transaction *transaction)\n+static void files_transaction_free(struct ref_transaction *transaction)\n {\n \tint i;\n \n@@ -2812,13 +2812,13 @@ static struct ref_update *add_update(struct ref_transaction *transaction,\n \treturn update;\n }\n \n-int transaction_update_reflog(struct ref_transaction *transaction,\n-\t\t\t      const char *refname,\n-\t\t\t      const unsigned char *new_sha1,\n-\t\t\t      const unsigned char *old_sha1,\n-\t\t\t      struct reflog_committer_info *ci,\n-\t\t\t      const char *msg, int flags,\n-\t\t\t      struct strbuf *err)\n+static int files_transaction_update_reflog(struct ref_transaction *transaction,\n+\t\t\t\t\t   const char *refname,\n+\t\t\t\t\t   const unsigned char *new_sha1,\n+\t\t\t\t\t   const unsigned char *old_sha1,\n+\t\t\t\t\t   struct reflog_committer_info *ci,\n+\t\t\t\t\t   const char *msg, int flags,\n+\t\t\t\t\t   struct strbuf *err)\n {\n \tstruct ref_update *update;\n \tint i;\n@@ -2865,12 +2865,13 @@ int transaction_update_reflog(struct ref_transaction *transaction,\n \treturn 0;\n }\n \n-int transaction_update_sha1(struct ref_transaction *transaction,\n-\t\t\t    const char *refname,\n-\t\t\t    const unsigned char *new_sha1,\n-\t\t\t    const unsigned char *old_sha1,\n-\t\t\t    int flags, int have_old, const char *msg,\n-\t\t\t    struct strbuf *err)\n+static int files_transaction_update_sha1(struct ref_transaction *transaction,\n+\t\t\t\t\t const char *refname,\n+\t\t\t\t\t const unsigned char *new_sha1,\n+\t\t\t\t\t const unsigned char *old_sha1,\n+\t\t\t\t\t int flags, int have_old,\n+\t\t\t\t\t const char *msg,\n+\t\t\t\t\t struct strbuf *err)\n {\n \tstruct ref_update *update;\n \n@@ -2897,11 +2898,11 @@ int transaction_update_sha1(struct ref_transaction *transaction,\n \treturn 0;\n }\n \n-int transaction_create_sha1(struct ref_transaction *transaction,\n-\t\t\t    const char *refname,\n-\t\t\t    const unsigned char *new_sha1,\n-\t\t\t    int flags, const char *msg,\n-\t\t\t    struct strbuf *err)\n+static int files_transaction_create_sha1(struct ref_transaction *transaction,\n+\t\t\t\t\t const char *refname,\n+\t\t\t\t\t const unsigned char *new_sha1,\n+\t\t\t\t\t int flags, const char *msg,\n+\t\t\t\t\t struct strbuf *err)\n {\n \tif (transaction->state != REF_TRANSACTION_OPEN)\n \t\tdie(\"BUG: create called for transaction that is not open\");\n@@ -2913,11 +2914,12 @@ int transaction_create_sha1(struct ref_transaction *transaction,\n \t\t\t\t       null_sha1, flags, 1, msg, err);\n }\n \n-int transaction_delete_sha1(struct ref_transaction *transaction,\n-\t\t\t    const char *refname,\n-\t\t\t    const unsigned char *old_sha1,\n-\t\t\t    int flags, int have_old, const char *msg,\n-\t\t\t    struct strbuf *err)\n+static int files_transaction_delete_sha1(struct ref_transaction *transaction,\n+\t\t\t\t\t const char *refname,\n+\t\t\t\t\t const unsigned char *old_sha1,\n+\t\t\t\t\t int flags, int have_old,\n+\t\t\t\t\t const char *msg,\n+\t\t\t\t\t struct strbuf *err)\n {\n \tif (transaction->state != REF_TRANSACTION_OPEN)\n \t\tdie(\"BUG: delete called for transaction that is not open\");\n@@ -2959,8 +2961,8 @@ static int ref_update_reject_duplicates(struct ref_update **updates, int n,\n \treturn 0;\n }\n \n-int transaction_commit(struct ref_transaction *transaction,\n-\t\t       struct strbuf *err)\n+static int files_transaction_commit(struct ref_transaction *transaction,\n+\t\t\t\t    struct strbuf *err)\n {\n \tint ret = 0, delnum = 0, i, df_conflict = 0, need_repack = 0;\n \tint num_updates = 0;\n@@ -3284,3 +3286,15 @@ cleanup:\n \t\tret = -2;\n \treturn ret;\n }\n+\n+struct ref_be refs_files = {\n+\tfiles_transaction_begin,\n+\tfiles_transaction_update_sha1,\n+\tfiles_transaction_create_sha1,\n+\tfiles_transaction_delete_sha1,\n+\tfiles_transaction_update_reflog,\n+\tfiles_transaction_commit,\n+\tfiles_transaction_free,\n+};\n+\n+struct ref_be *refs = &refs_files;\ndiff --git a/refs.c b/refs.c\nindex 6b434ad..b8c942f 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -801,3 +801,58 @@ int head_ref_namespaced(each_ref_fn fn, void *cb_data)\n \n \treturn ret;\n }\n+\n+\n+/* backend functions */\n+struct ref_transaction *transaction_begin(struct strbuf *err)\n+{\n+\treturn refs->transaction_begin(err);\n+}\n+\n+int transaction_update_sha1(struct ref_transaction *transaction,\n+\t\t\t    const char *refname, const unsigned char *new_sha1,\n+\t\t\t    const unsigned char *old_sha1, int flags,\n+\t\t\t    int have_old, const char *msg, struct strbuf *err)\n+{\n+\treturn refs->transaction_update_sha1(transaction, refname, new_sha1,\n+\t\t\t\t\t     old_sha1, flags, have_old, msg,\n+\t\t\t\t\t     err);\n+}\n+\n+int transaction_create_sha1(struct ref_transaction *transaction,\n+\t\t\t    const char *refname, const unsigned char *new_sha1,\n+\t\t\t    int flags, const char *msg, struct strbuf *err)\n+{\n+\treturn refs->transaction_create_sha1(transaction, refname, new_sha1,\n+\t\t\t\t\t     flags, msg, err);\n+}\n+int transaction_delete_sha1(struct ref_transaction *transaction,\n+\t\t\t    const char *refname, const unsigned char *old_sha1,\n+\t\t\t    int flags, int have_old, const char *msg,\n+\t\t\t    struct strbuf *err)\n+{\n+\treturn refs->transaction_delete_sha1(transaction, refname, old_sha1,\n+\t\t\t\t\t     flags, have_old, msg, err);\n+}\n+\n+int transaction_update_reflog(struct ref_transaction *transaction,\n+\t\t\t      const char *refname,\n+\t\t\t      const unsigned char *new_sha1,\n+\t\t\t      const unsigned char *old_sha1,\n+\t\t\t      struct reflog_committer_info *ci,\n+\t\t\t      const char *msg, int flags,\n+\t\t\t      struct strbuf *err)\n+{\n+\treturn refs->transaction_update_reflog(transaction, refname, new_sha1,\n+\t\t\t\t\t       old_sha1, ci, msg, flags, err);\n+}\n+\n+int transaction_commit(struct ref_transaction *transaction, struct strbuf *err)\n+{\n+\treturn refs->transaction_commit(transaction, err);\n+}\n+\n+void transaction_free(struct ref_transaction *transaction)\n+{\n+\treturn refs->transaction_free(transaction);\n+}\ndiff --git a/refs.h b/refs.h\nindex a14fc5d..4b669f5 100644\n--- a/refs.h\n+++ b/refs.h\n@@ -350,4 +350,39 @@ int update_ref(const char *action, const char *refname,\n extern int parse_hide_refs_config(const char *var, const char *value, const char *);\n extern int ref_is_hidden(const char *);\n \n+\n+/* refs backends */\n+typedef struct ref_transaction *(*transaction_begin_fn)(struct strbuf *err);\n+typedef int (*transaction_update_sha1_fn)(struct ref_transaction *transaction,\n+\t\tconst char *refname, const unsigned char *new_sha1,\n+\t\tconst unsigned char *old_sha1, int flags, int have_old,\n+\t\tconst char *msg, struct strbuf *err);\n+typedef int (*transaction_create_sha1_fn)(struct ref_transaction *transaction,\n+\t\tconst char *refname, const unsigned char *new_sha1,\n+\t\tint flags, const char *msg, struct strbuf *err);\n+typedef int (*transaction_delete_sha1_fn)(struct ref_transaction *transaction,\n+\t\tconst char *refname, const unsigned char *old_sha1,\n+\t\tint flags, int have_old, const char *msg, struct strbuf *err);\n+typedef int (*transaction_update_reflog_fn)(\n+\t\tstruct ref_transaction *transaction,\n+\t\tconst char *refname, const unsigned char *new_sha1,\n+\t\tconst unsigned char *old_sha1,\n+\t\tstruct reflog_committer_info *ci,\n+\t\tconst char *msg, int flags, struct strbuf *err);\n+typedef int (*transaction_commit_fn)(struct ref_transaction *transaction,\n+\t\t\t\t       struct strbuf *err);\n+typedef void (*transaction_free_fn)(struct ref_transaction *transaction);\n+\n+struct ref_be {\n+\ttransaction_begin_fn transaction_begin;\n+\ttransaction_update_sha1_fn transaction_update_sha1;\n+\ttransaction_create_sha1_fn transaction_create_sha1;\n+\ttransaction_delete_sha1_fn transaction_delete_sha1;\n+\ttransaction_update_reflog_fn transaction_update_reflog;\n+\ttransaction_commit_fn transaction_commit;\n+\ttransaction_free_fn transaction_free;\n+};\n+\n+extern struct ref_be *refs;\n+\n #endif /* REFS_H */\n-- \n2.0.1.552.g1af257a\n"},{"id":"247938","messageId":"1408465847-30384-21-git-send-email-sahlberg@google.com","threadId":"37379","inReplyTo":"1408465847-30384-1-git-send-email-sahlberg@google.com","subject":"[PATCH v3 20/23] refs-be-files.c: add reflog backend methods","fromName":"Ronnie Sahlberg","fromEmail":"sahlberg@google.com","sentAt":"2014-08-19T16:30:44Z","receivedAt":"2014-08-19T16:30:44Z","isPatch":true,"sender":{"key":"sahlberg@google.com","avatar":"https://avatars.githubusercontent.com/u/7320636?v=4"},"body":"Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>\n---\n refs-be-files.c | 21 +++++++++++++++------\n refs.c          | 32 ++++++++++++++++++++++++++++++++\n refs.h          | 16 ++++++++++++++++\n 3 files changed, 63 insertions(+), 6 deletions(-)\n\ndiff --git a/refs-be-files.c b/refs-be-files.c\nindex 27eafd0..464d488 100644\n--- a/refs-be-files.c\n+++ b/refs-be-files.c\n@@ -2251,7 +2251,7 @@ static int copy_msg(char *buf, const char *msg)\n }\n \n /* This function must set a meaningful errno on failure */\n-int create_reflog(const char *refname)\n+static int files_create_reflog(const char *refname)\n {\n \tint logfd, oflags = O_APPEND | O_WRONLY;\n \tchar logfile[PATH_MAX];\n@@ -2516,7 +2516,7 @@ int create_symref(const char *ref_target, const char *refs_heads_master,\n \treturn 0;\n }\n \n-int reflog_exists(const char *refname)\n+static int files_reflog_exists(const char *refname)\n {\n \tstruct stat st;\n \n@@ -2524,7 +2524,7 @@ int reflog_exists(const char *refname)\n \t\tS_ISREG(st.st_mode);\n }\n \n-int delete_reflog(const char *refname)\n+static int files_delete_reflog(const char *refname)\n {\n \treturn remove_path(git_path(\"logs/%s\", refname));\n }\n@@ -2568,7 +2568,9 @@ static char *find_beginning_of_line(char *bob, char *scan)\n \treturn scan;\n }\n \n-int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn, void *cb_data)\n+static int files_for_each_reflog_ent_reverse(const char *refname,\n+\t\t\t\t\t     each_reflog_ent_fn fn,\n+\t\t\t\t\t     void *cb_data)\n {\n \tstruct strbuf sb = STRBUF_INIT;\n \tFILE *logfp;\n@@ -2645,7 +2647,8 @@ int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn, void\n \treturn ret;\n }\n \n-int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn, void *cb_data)\n+static int files_for_each_reflog_ent(const char *refname,\n+\t\t\t\t     each_reflog_ent_fn fn, void *cb_data)\n {\n \tFILE *logfp;\n \tstruct strbuf sb = STRBUF_INIT;\n@@ -2706,7 +2709,7 @@ static int do_for_each_reflog(struct strbuf *name, each_ref_fn fn, void *cb_data\n \treturn retval;\n }\n \n-int for_each_reflog(each_ref_fn fn, void *cb_data)\n+static int files_for_each_reflog(each_ref_fn fn, void *cb_data)\n {\n \tint retval;\n \tstruct strbuf name;\n@@ -3295,6 +3298,12 @@ struct ref_be refs_files = {\n \tfiles_transaction_update_reflog,\n \tfiles_transaction_commit,\n \tfiles_transaction_free,\n+\tfiles_for_each_reflog_ent,\n+\tfiles_for_each_reflog_ent_reverse,\n+\tfiles_for_each_reflog,\n+\tfiles_reflog_exists,\n+\tfiles_create_reflog,\n+\tfiles_delete_reflog,\n };\n \n struct ref_be *refs = &refs_files;\ndiff --git a/refs.c b/refs.c\nindex b8c942f..2db1a74 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -856,3 +856,35 @@ void transaction_free(struct ref_transaction *transaction)\n {\n \treturn refs->transaction_free(transaction);\n }\n+\n+int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn,\n+\t\t\t\tvoid *cb_data)\n+{\n+\treturn refs->for_each_reflog_ent_reverse(refname, fn, cb_data);\n+}\n+\n+int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn,\n+\t\t\tvoid *cb_data)\n+{\n+\treturn refs->for_each_reflog_ent(refname, fn, cb_data);\n+}\n+\n+int for_each_reflog(each_ref_fn fn, void *cb_data)\n+{\n+\treturn refs->for_each_reflog(fn, cb_data);\n+}\n+\n+int reflog_exists(const char *refname)\n+{\n+\treturn refs->reflog_exists(refname);\n+}\n+\n+int create_reflog(const char *refname)\n+{\n+\treturn refs->create_reflog(refname);\n+}\n+\n+int delete_reflog(const char *refname)\n+{\n+\treturn refs->delete_reflog(refname);\n+}\ndiff --git a/refs.h b/refs.h\nindex 4b669f5..0a68986 100644\n--- a/refs.h\n+++ b/refs.h\n@@ -372,6 +372,16 @@ typedef int (*transaction_update_reflog_fn)(\n typedef int (*transaction_commit_fn)(struct ref_transaction *transaction,\n \t\t\t\t       struct strbuf *err);\n typedef void (*transaction_free_fn)(struct ref_transaction *transaction);\n+typedef int (*for_each_reflog_ent_fn)(const char *refname,\n+\t\t\t\t      each_reflog_ent_fn fn,\n+\t\t\t\t      void *cb_data);\n+typedef int (*for_each_reflog_ent_reverse_fn)(const char *refname,\n+\t\t\t\t\t      each_reflog_ent_fn fn,\n+\t\t\t\t\t      void *cb_data);\n+typedef int (*for_each_reflog_fn)(each_ref_fn fn, void *cb_data);\n+typedef int (*reflog_exists_fn)(const char *refname);\n+typedef int (*create_reflog_fn)(const char *refname);\n+typedef int (*delete_reflog_fn)(const char *refname);\n \n struct ref_be {\n \ttransaction_begin_fn transaction_begin;\n@@ -381,6 +391,12 @@ struct ref_be {\n \ttransaction_update_reflog_fn transaction_update_reflog;\n \ttransaction_commit_fn transaction_commit;\n \ttransaction_free_fn transaction_free;\n+\tfor_each_reflog_ent_fn for_each_reflog_ent;\n+\tfor_each_reflog_ent_reverse_fn for_each_reflog_ent_reverse;\n+\tfor_each_reflog_fn for_each_reflog;\n+\treflog_exists_fn reflog_exists;\n+\tcreate_reflog_fn create_reflog;\n+\tdelete_reflog_fn delete_reflog;\n };\n \n extern struct ref_be *refs;\n-- \n2.0.1.552.g1af257a\n"},{"id":"247935","messageId":"1408465847-30384-22-git-send-email-sahlberg@google.com","threadId":"37379","inReplyTo":"1408465847-30384-1-git-send-email-sahlberg@google.com","subject":"[PATCH v3 21/23] refs-be-files.c: add methods for misc ref operations","fromName":"Ronnie Sahlberg","fromEmail":"sahlberg@google.com","sentAt":"2014-08-19T16:30:45Z","receivedAt":"2014-08-19T16:30:45Z","isPatch":true,"sender":{"key":"sahlberg@google.com","avatar":"https://avatars.githubusercontent.com/u/7320636?v=4"},"body":"Add ref backend methods for:\nresolve_ref_unsafe, is_refname_available, pack_refs, peel_ref,\ncreate_symref, resolve_gitlink_ref.\n\nSigned-off-by: Ronnie Sahlberg <sahlberg@google.com>\n---\n refs-be-files.c | 25 ++++++++++++++++++-------\n refs.c          | 33 +++++++++++++++++++++++++++++++++\n refs.h          | 18 ++++++++++++++++++\n 3 files changed, 69 insertions(+), 7 deletions(-)\n\ndiff --git a/refs-be-files.c b/refs-be-files.c\nindex 464d488..b09f0fc 100644\n--- a/refs-be-files.c\n+++ b/refs-be-files.c\n@@ -1114,7 +1114,8 @@ static struct ref_dir *get_loose_refs(struct ref_cache *refs)\n \treturn get_ref_dir(refs->loose);\n }\n \n-int is_refname_available(const char *refname, const char **skip, int skipnum)\n+static int files_is_refname_available(const char *refname, const char **skip,\n+\t\t\t\t      int skipnum)\n {\n \tif (!is_refname_available_dir(refname, get_packed_refs(&ref_cache),\n \t\t\t\t      skip, skipnum))\n@@ -1188,7 +1189,8 @@ static int resolve_gitlink_ref_recursive(struct ref_cache *refs,\n \treturn resolve_gitlink_ref_recursive(refs, p, sha1, recursion+1);\n }\n \n-int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *sha1)\n+static int files_resolve_gitlink_ref(const char *path, const char *refname,\n+\t\t\t\t     unsigned char *sha1)\n {\n \tint len = strlen(path), retval;\n \tchar *submodule;\n@@ -1247,7 +1249,9 @@ static const char *handle_missing_loose_ref(const char *refname,\n }\n \n /* This function needs to return a meaningful errno on failure */\n-const char *resolve_ref_unsafe(const char *refname, unsigned char *sha1, int flags, int *ref_flag)\n+static const char *files_resolve_ref_unsafe(const char *refname,\n+\t\t\t\t\t    unsigned char *sha1, int flags,\n+\t\t\t\t\t    int *ref_flag)\n {\n \tint depth = MAXDEPTH;\n \tssize_t len;\n@@ -1466,7 +1470,7 @@ static enum peel_status peel_entry(struct ref_entry *entry, int repeel)\n \treturn status;\n }\n \n-int peel_ref(const char *refname, unsigned char *sha1)\n+static int files_peel_ref(const char *refname, unsigned char *sha1)\n {\n \tint flag;\n \tunsigned char base[20];\n@@ -2080,7 +2084,7 @@ static void prune_refs(struct ref_to_prune *r)\n \t}\n }\n \n-int pack_refs(unsigned int flags, struct strbuf *err)\n+static int files_pack_refs(unsigned int flags, struct strbuf *err)\n {\n \tstruct pack_refs_cb_data cbdata;\n \n@@ -2453,8 +2457,9 @@ static int write_ref_sha1(struct ref_lock *lock,\n \treturn 0;\n }\n \n-int create_symref(const char *ref_target, const char *refs_heads_master,\n-\t\t  const char *logmsg)\n+static int files_create_symref(const char *ref_target,\n+\t\t\t       const char *refs_heads_master,\n+\t\t\t       const char *logmsg)\n {\n \tconst char *lockpath;\n \tchar ref[1000];\n@@ -3304,6 +3309,12 @@ struct ref_be refs_files = {\n \tfiles_reflog_exists,\n \tfiles_create_reflog,\n \tfiles_delete_reflog,\n+\tfiles_resolve_ref_unsafe,\n+\tfiles_is_refname_available,\n+\tfiles_pack_refs,\n+\tfiles_peel_ref,\n+\tfiles_create_symref,\n+\tfiles_resolve_gitlink_ref,\n };\n \n struct ref_be *refs = &refs_files;\ndiff --git a/refs.c b/refs.c\nindex 2db1a74..60b6241 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -888,3 +888,36 @@ int delete_reflog(const char *refname)\n {\n \treturn refs->delete_reflog(refname);\n }\n+\n+const char *resolve_ref_unsafe(const char *ref, unsigned char *sha1,\n+\t\t\t       int reading, int *flag)\n+{\n+\treturn refs->resolve_ref_unsafe(ref, sha1, reading, flag);\n+}\n+\n+int is_refname_available(const char *refname, const char **skip, int skipnum)\n+{\n+\treturn refs->is_refname_available(refname, skip, skipnum);\n+}\n+\n+int pack_refs(unsigned int flags, struct strbuf *err)\n+{\n+\treturn refs->pack_refs(flags, err);\n+}\n+\n+int peel_ref(const char *refname, unsigned char *sha1)\n+{\n+\treturn refs->peel_ref(refname, sha1);\n+}\n+\n+int create_symref(const char *ref_target, const char *refs_heads_master,\n+\t\t  const char *logmsg)\n+{\n+\treturn refs->create_symref(ref_target, refs_heads_master, logmsg);\n+}\n+\n+int resolve_gitlink_ref(const char *path, const char *refname,\n+\t\t\tunsigned char *sha1)\n+{\n+\treturn refs->resolve_gitlink_ref(path, refname, sha1);\n+}\ndiff --git a/refs.h b/refs.h\nindex 0a68986..5257437 100644\n--- a/refs.h\n+++ b/refs.h\n@@ -382,6 +382,18 @@ typedef int (*for_each_reflog_fn)(each_ref_fn fn, void *cb_data);\n typedef int (*reflog_exists_fn)(const char *refname);\n typedef int (*create_reflog_fn)(const char *refname);\n typedef int (*delete_reflog_fn)(const char *refname);\n+typedef const char *(*resolve_ref_unsafe_fn)(const char *ref,\n+\t\tunsigned char *sha1, int reading, int *flag);\n+\n+typedef int (*is_refname_available_fn)(const char *refname, const char **skip,\n+\t\t\t\t       int skipnum);\n+typedef int (*pack_refs_fn)(unsigned int flags, struct strbuf *err);\n+typedef int (*peel_ref_fn)(const char *refname, unsigned char *sha1);\n+typedef int (*create_symref_fn)(const char *ref_target,\n+\t\t\t\tconst char *refs_heads_master,\n+\t\t\t\tconst char *logmsg);\n+typedef int (*resolve_gitlink_ref_fn)(const char *path, const char *refname,\n+\t\t\t\t      unsigned char *sha1);\n \n struct ref_be {\n \ttransaction_begin_fn transaction_begin;\n@@ -397,6 +409,12 @@ struct ref_be {\n \treflog_exists_fn reflog_exists;\n \tcreate_reflog_fn create_reflog;\n \tdelete_reflog_fn delete_reflog;\n+\tresolve_ref_unsafe_fn resolve_ref_unsafe;\n+\tis_refname_available_fn is_refname_available;\n+\tpack_refs_fn pack_refs;\n+\tpeel_ref_fn peel_ref;\n+\tcreate_symref_fn create_symref;\n+\tresolve_gitlink_ref_fn resolve_gitlink_ref;\n };\n \n extern struct ref_be *refs;\n-- \n2.0.1.552.g1af257a\n"},{"id":"247944","messageId":"1408465847-30384-23-git-send-email-sahlberg@google.com","threadId":"37379","inReplyTo":"1408465847-30384-1-git-send-email-sahlberg@google.com","subject":"[PATCH v3 22/23] refs-be-files.c: add methods for head_ref*","fromName":"Ronnie Sahlberg","fromEmail":"sahlberg@google.com","sentAt":"2014-08-19T16:30:46Z","receivedAt":"2014-08-19T16:30:46Z","isPatch":true,"sender":{"key":"sahlberg@google.com","avatar":"https://avatars.githubusercontent.com/u/7320636?v=4"},"body":"Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>\n---\n refs-be-files.c |  7 +++++--\n refs.c          | 10 ++++++++++\n refs.h          |  5 +++++\n 3 files changed, 20 insertions(+), 2 deletions(-)\n\ndiff --git a/refs-be-files.c b/refs-be-files.c\nindex b09f0fc..910663b 100644\n--- a/refs-be-files.c\n+++ b/refs-be-files.c\n@@ -1603,12 +1603,13 @@ static int do_head_ref(const char *submodule, each_ref_fn fn, void *cb_data)\n \treturn 0;\n }\n \n-int head_ref(each_ref_fn fn, void *cb_data)\n+static int files_head_ref(each_ref_fn fn, void *cb_data)\n {\n \treturn do_head_ref(NULL, fn, cb_data);\n }\n \n-int head_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)\n+static int files_head_ref_submodule(const char *submodule, each_ref_fn fn,\n+\t\t\t\t    void *cb_data)\n {\n \treturn do_head_ref(submodule, fn, cb_data);\n }\n@@ -3315,6 +3316,8 @@ struct ref_be refs_files = {\n \tfiles_peel_ref,\n \tfiles_create_symref,\n \tfiles_resolve_gitlink_ref,\n+\tfiles_head_ref,\n+\tfiles_head_ref_submodule,\n };\n \n struct ref_be *refs = &refs_files;\ndiff --git a/refs.c b/refs.c\nindex 60b6241..841d905 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -921,3 +921,13 @@ int resolve_gitlink_ref(const char *path, const char *refname,\n {\n \treturn refs->resolve_gitlink_ref(path, refname, sha1);\n }\n+\n+int head_ref(each_ref_fn fn, void *cb_data)\n+{\n+\treturn refs->head_ref(fn, cb_data);\n+}\n+\n+int head_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)\n+{\n+\treturn refs->head_ref_submodule(submodule, fn, cb_data);\n+}\ndiff --git a/refs.h b/refs.h\nindex 5257437..92f8f44 100644\n--- a/refs.h\n+++ b/refs.h\n@@ -394,6 +394,9 @@ typedef int (*create_symref_fn)(const char *ref_target,\n \t\t\t\tconst char *logmsg);\n typedef int (*resolve_gitlink_ref_fn)(const char *path, const char *refname,\n \t\t\t\t      unsigned char *sha1);\n+typedef int (*head_ref_fn)(each_ref_fn fn, void *cb_data);\n+typedef int (*head_ref_submodule_fn)(const char *submodule, each_ref_fn fn,\n+\t\t\t\t     void *cb_data);\n \n struct ref_be {\n \ttransaction_begin_fn transaction_begin;\n@@ -415,6 +418,8 @@ struct ref_be {\n \tpeel_ref_fn peel_ref;\n \tcreate_symref_fn create_symref;\n \tresolve_gitlink_ref_fn resolve_gitlink_ref;\n+\thead_ref_fn head_ref;\n+\thead_ref_submodule_fn head_ref_submodule;\n };\n \n extern struct ref_be *refs;\n-- \n2.0.1.552.g1af257a\n"},{"id":"247942","messageId":"1408465847-30384-24-git-send-email-sahlberg@google.com","threadId":"37379","inReplyTo":"1408465847-30384-1-git-send-email-sahlberg@google.com","subject":"[PATCH v3 23/23] refs-be-files.c: add methods for the ref iterators","fromName":"Ronnie Sahlberg","fromEmail":"sahlberg@google.com","sentAt":"2014-08-19T16:30:47Z","receivedAt":"2014-08-19T16:30:47Z","isPatch":true,"sender":{"key":"sahlberg@google.com","avatar":"https://avatars.githubusercontent.com/u/7320636?v=4"},"body":"Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>\n---\n refs-be-files.c | 21 ++++++++++++++-------\n refs.c          | 36 ++++++++++++++++++++++++++++++++++++\n refs.h          | 18 ++++++++++++++++++\n 3 files changed, 68 insertions(+), 7 deletions(-)\n\ndiff --git a/refs-be-files.c b/refs-be-files.c\nindex 910663b..7c0ab25 100644\n--- a/refs-be-files.c\n+++ b/refs-be-files.c\n@@ -1614,33 +1614,33 @@ static int files_head_ref_submodule(const char *submodule, each_ref_fn fn,\n \treturn do_head_ref(submodule, fn, cb_data);\n }\n \n-int for_each_ref(each_ref_fn fn, void *cb_data)\n+static int files_for_each_ref(each_ref_fn fn, void *cb_data)\n {\n \treturn do_for_each_ref(&ref_cache, \"\", fn, 0, 0, cb_data);\n }\n \n-int for_each_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)\n+static int files_for_each_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)\n {\n \treturn do_for_each_ref(get_ref_cache(submodule), \"\", fn, 0, 0, cb_data);\n }\n \n-int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data)\n+static int files_for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data)\n {\n \treturn do_for_each_ref(&ref_cache, prefix, fn, strlen(prefix), 0, cb_data);\n }\n \n-int for_each_ref_in_submodule(const char *submodule, const char *prefix,\n+static int files_for_each_ref_in_submodule(const char *submodule, const char *prefix,\n \t\teach_ref_fn fn, void *cb_data)\n {\n \treturn do_for_each_ref(get_ref_cache(submodule), prefix, fn, strlen(prefix), 0, cb_data);\n }\n \n-int for_each_replace_ref(each_ref_fn fn, void *cb_data)\n+static int files_for_each_replace_ref(each_ref_fn fn, void *cb_data)\n {\n \treturn do_for_each_ref(&ref_cache, \"refs/replace/\", fn, 13, 0, cb_data);\n }\n \n-int for_each_namespaced_ref(each_ref_fn fn, void *cb_data)\n+static int files_for_each_namespaced_ref(each_ref_fn fn, void *cb_data)\n {\n \tstruct strbuf buf = STRBUF_INIT;\n \tint ret;\n@@ -1650,7 +1650,7 @@ int for_each_namespaced_ref(each_ref_fn fn, void *cb_data)\n \treturn ret;\n }\n \n-int for_each_rawref(each_ref_fn fn, void *cb_data)\n+static int files_for_each_rawref(each_ref_fn fn, void *cb_data)\n {\n \treturn do_for_each_ref(&ref_cache, \"\", fn, 0,\n \t\t\t       DO_FOR_EACH_INCLUDE_BROKEN, cb_data);\n@@ -3318,6 +3318,13 @@ struct ref_be refs_files = {\n \tfiles_resolve_gitlink_ref,\n \tfiles_head_ref,\n \tfiles_head_ref_submodule,\n+\tfiles_for_each_ref,\n+\tfiles_for_each_ref_submodule,\n+\tfiles_for_each_ref_in,\n+\tfiles_for_each_ref_in_submodule,\n+\tfiles_for_each_rawref,\n+\tfiles_for_each_namespaced_ref,\n+\tfiles_for_each_replace_ref,\n };\n \n struct ref_be *refs = &refs_files;\ndiff --git a/refs.c b/refs.c\nindex 841d905..ceee979 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -931,3 +931,39 @@ int head_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)\n {\n \treturn refs->head_ref_submodule(submodule, fn, cb_data);\n }\n+\n+int for_each_ref(each_ref_fn fn, void *cb_data)\n+{\n+\treturn refs->for_each_ref(fn, cb_data);\n+}\n+\n+int for_each_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)\n+{\n+\treturn refs->for_each_ref_submodule(submodule, fn, cb_data);\n+}\n+\n+int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data)\n+{\n+\treturn refs->for_each_ref_in(prefix, fn, cb_data);\n+}\n+\n+int for_each_ref_in_submodule(const char *submodule, const char *prefix,\n+\t\t\t      each_ref_fn fn, void *cb_data)\n+{\n+\treturn refs->for_each_ref_in_submodule(submodule, prefix, fn, cb_data);\n+}\n+\n+int for_each_rawref(each_ref_fn fn, void *cb_data)\n+{\n+\treturn refs->for_each_rawref(fn, cb_data);\n+}\n+\n+int for_each_namespaced_ref(each_ref_fn fn, void *cb_data)\n+{\n+\treturn refs->for_each_namespaced_ref(fn, cb_data);\n+}\n+\n+int for_each_replace_ref(each_ref_fn fn, void *cb_data)\n+{\n+\treturn refs->for_each_replace_ref(fn, cb_data);\n+}\ndiff --git a/refs.h b/refs.h\nindex 92f8f44..bd3a0d4 100644\n--- a/refs.h\n+++ b/refs.h\n@@ -397,6 +397,17 @@ typedef int (*resolve_gitlink_ref_fn)(const char *path, const char *refname,\n typedef int (*head_ref_fn)(each_ref_fn fn, void *cb_data);\n typedef int (*head_ref_submodule_fn)(const char *submodule, each_ref_fn fn,\n \t\t\t\t     void *cb_data);\n+typedef int (*for_each_ref_fn)(each_ref_fn fn, void *cb_data);\n+typedef int (*for_each_ref_submodule_fn)(const char *submodule, each_ref_fn fn,\n+\t\t\t\t\t void *cb_data);\n+typedef int (*for_each_ref_in_fn)(const char *prefix, each_ref_fn fn,\n+\t\t\t\t  void *cb_data);\n+typedef int (*for_each_ref_in_submodule_fn)(const char *submodule,\n+\t\t\t\t\t    const char *prefix,\n+\t\t\t\t\t    each_ref_fn fn, void *cb_data);\n+typedef int (*for_each_rawref_fn)(each_ref_fn fn, void *cb_data);\n+typedef int (*for_each_namespaced_ref_fn)(each_ref_fn fn, void *cb_data);\n+typedef int (*for_each_replace_ref_fn)(each_ref_fn fn, void *cb_data);\n \n struct ref_be {\n \ttransaction_begin_fn transaction_begin;\n@@ -420,6 +431,13 @@ struct ref_be {\n \tresolve_gitlink_ref_fn resolve_gitlink_ref;\n \thead_ref_fn head_ref;\n \thead_ref_submodule_fn head_ref_submodule;\n+\tfor_each_ref_fn for_each_ref;\n+\tfor_each_ref_submodule_fn for_each_ref_submodule;\n+\tfor_each_ref_in_fn for_each_ref_in;\n+\tfor_each_ref_in_submodule_fn for_each_ref_in_submodule;\n+\tfor_each_rawref_fn for_each_rawref;\n+\tfor_each_namespaced_ref_fn for_each_namespaced_ref;\n+\tfor_each_replace_ref_fn for_each_replace_ref;\n };\n \n extern struct ref_be *refs;\n-- \n2.0.1.552.g1af257a\n"},{"id":"248348","messageId":"xmqqd2bngcpf.fsf@gitster.dls.corp.google.com","threadId":"37379","inReplyTo":"1408465847-30384-4-git-send-email-sahlberg@google.com","subject":"Re: [PATCH v3 03/23] refs.c: add a new refs.c file to hold all common refs code","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-08-26T21:31:24Z","receivedAt":"2014-08-26T21:31:24Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ronnie Sahlberg <sahlberg@google.com> writes:\n\n> Create a new erfs.c file that will be used to hold all the refs\n> code that is backend agnostic and will be shared across all backends.\n>\n> The reason we renamed everything to refs-be-files.c in the previous patch\n> and now start moving the common code back to the new refs.c file\n> instead of the other way around is the etive volumes of code.\n\nHuh?  Why not create refs-be-files.c and move whatever need to be\nthere over there, instead of rename the file and move things that\nshouldn't have been moved back like this?\n\nPuzzled.\n\nI do not see 02/23 here, but I am assuming that is is just\n\n    git mv refs.c refs-be-files.c\n\nwhich may have been a seven-line patch with \"format-patch -M\" ;-)\n\n>\n> With the ref_cache, packed refs and loose ref handling that are all\n> part of the files based implementation the backend specific part\n> of the old refs.c file is several times larger than the backend agnostic\n> part. Therefore it makes more sense to first rename everything to be\n> part of the files based backend and then move the parts that can be used\n> as common code back to refs.c.\n>\n> Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>\n> ---\n>  Makefile | 1 +\n>  refs.c   | 3 +++\n>  2 files changed, 4 insertions(+)\n>  create mode 100644 refs.c\n>\n> diff --git a/Makefile b/Makefile\n> index e010ad1..937d22a 100644\n> --- a/Makefile\n> +++ b/Makefile\n> @@ -857,6 +857,7 @@ LIB_OBJS += quote.o\n>  LIB_OBJS += reachable.o\n>  LIB_OBJS += read-cache.o\n>  LIB_OBJS += reflog-walk.o\n> +LIB_OBJS += refs.o\n>  LIB_OBJS += refs-be-files.o\n>  LIB_OBJS += remote.o\n>  LIB_OBJS += replace_object.o\n> diff --git a/refs.c b/refs.c\n> new file mode 100644\n> index 0000000..77492ff\n> --- /dev/null\n> +++ b/refs.c\n> @@ -0,0 +1,3 @@\n> +/*\n> + * Common refs code for all backends.\n> + */\n"},{"id":"248349","messageId":"xmqq8umbgcd9.fsf@gitster.dls.corp.google.com","threadId":"37379","inReplyTo":"1408465847-30384-20-git-send-email-sahlberg@google.com","subject":"Re: [PATCH v3 19/23] refs-be-files.c: add a backend method structure with transaction functions","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-08-26T21:38:42Z","receivedAt":"2014-08-26T21:38:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ronnie Sahlberg <sahlberg@google.com> writes:\n\n> diff --git a/refs-be-files.c b/refs-be-files.c\n> index e58a7e1..27eafd0 100644\n> --- a/refs-be-files.c\n> +++ b/refs-be-files.c\n> ...\n> +struct ref_be refs_files = {\n> +\tfiles_transaction_begin,\n> +\tfiles_transaction_update_sha1,\n> +\tfiles_transaction_create_sha1,\n> +\tfiles_transaction_delete_sha1,\n> +\tfiles_transaction_update_reflog,\n> +\tfiles_transaction_commit,\n> +\tfiles_transaction_free,\n> +};\n> +\n> +struct ref_be *refs = &refs_files;\n\n> diff --git a/refs.c b/refs.c\n> index 6b434ad..b8c942f 100644\n> --- a/refs.c\n> +++ b/refs.c\n> ...\n> +void transaction_free(struct ref_transaction *transaction)\n> +{\n> +\treturn refs->transaction_free(transaction);\n> +}\n> diff --git a/refs.h b/refs.h\n> index a14fc5d..4b669f5 100644\n> --- a/refs.h\n> +++ b/refs.h\n> ...\n> +struct ref_be {\n> +\ttransaction_begin_fn transaction_begin;\n> +\ttransaction_update_sha1_fn transaction_update_sha1;\n> +\ttransaction_create_sha1_fn transaction_create_sha1;\n> +\ttransaction_delete_sha1_fn transaction_delete_sha1;\n> +\ttransaction_update_reflog_fn transaction_update_reflog;\n> +\ttransaction_commit_fn transaction_commit;\n> +\ttransaction_free_fn transaction_free;\n> +};\n> +\n> +extern struct ref_be *refs;\n> +\n>  #endif /* REFS_H */\n\nThe overall structure is certainly nice, but this means you only can\nLINK with one backend.  Is that what we really want?\n\nI would have expected something like this:\n\n  * In refs.c, there is a \"static struct ref_be *the_refs_backend\"\n    that points at the chosen singleton backend;\n\n  * Upon start-up, set_refs_backend() function that is exported from\n    refs.c can be used to set the_refs_backend;\n\n  * Each refs-be-frotz.c will export \"struct ref_be refs_frotz\" (or\n    perhaps \"struct refs_be refs_be_frotz\") to the outside world, so\n    that the start-up code can call set_refs_backend() with it.\n\n  * It is probably sensible to keep the_refs_backend default to\n    &refs_be_files.\n"},{"id":"248351","messageId":"CAL=YDWmsqDFUn1z6Z+YwPBGChqz_UctQsa9XRwv-R+Sx2=A6zg@mail.gmail.com","threadId":"37379","inReplyTo":"xmqqd2bngcpf.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH v3 03/23] refs.c: add a new refs.c file to hold all common refs code","fromName":"Ronnie Sahlberg","fromEmail":"sahlberg@google.com","sentAt":"2014-08-26T22:00:46Z","receivedAt":"2014-08-26T22:00:46Z","isPatch":true,"sender":{"key":"sahlberg@google.com","avatar":"https://avatars.githubusercontent.com/u/7320636?v=4"},"body":"On Tue, Aug 26, 2014 at 2:31 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Ronnie Sahlberg <sahlberg@google.com> writes:\n>\n>> Create a new erfs.c file that will be used to hold all the refs\n>> code that is backend agnostic and will be shared across all backends.\n>>\n>> The reason we renamed everything to refs-be-files.c in the previous patch\n>> and now start moving the common code back to the new refs.c file\n>> instead of the other way around is the etive volumes of code.\n>\n> Huh?  Why not create refs-be-files.c and move whatever need to be\n> there over there, instead of rename the file and move things that\n> shouldn't have been moved back like this?\n>\n\nThe reason is the relative size of the code. I could do it the other\nway but then\nthe changes that is moving the code would be much bigger.\n\nMoving it like this, by first renaming it to refs-be-files.c and then\nmoving the backend agnostic parts back\nis that the backend agnostic parts are mostly helper functions that\nare independent of eachother.\nThis makes it possible to move just a few functions at a time making\nthe individual changes smaller and easier to manage when there are\nmerge conflicts.\n\nA lot of the code that implements the actual files implementation for\nrefs storage implements the ref-cache/ref-dir/packed-refs/loose refs\netc.\nThis is all code that is intertwined and is difficult to split up.\nThus almost forcing me to move the whole 3000 lines of implementation\nin one single monolithic patch.\n\nI think \"first rename, then move the agnostic parts a small section at\na time\" was the least bad solution.\n\n\n\n\n> Puzzled.\n>\n> I do not see 02/23 here, but I am assuming that is is just\n>\n>     git mv refs.c refs-be-files.c\n>\n> which may have been a seven-line patch with \"format-patch -M\" ;-)\n>\n>>\n>> With the ref_cache, packed refs and loose ref handling that are all\n>> part of the files based implementation the backend specific part\n>> of the old refs.c file is several times larger than the backend agnostic\n>> part. Therefore it makes more sense to first rename everything to be\n>> part of the files based backend and then move the parts that can be used\n>> as common code back to refs.c.\n>>\n>> Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>\n>> ---\n>>  Makefile | 1 +\n>>  refs.c   | 3 +++\n>>  2 files changed, 4 insertions(+)\n>>  create mode 100644 refs.c\n>>\n>> diff --git a/Makefile b/Makefile\n>> index e010ad1..937d22a 100644\n>> --- a/Makefile\n>> +++ b/Makefile\n>> @@ -857,6 +857,7 @@ LIB_OBJS += quote.o\n>>  LIB_OBJS += reachable.o\n>>  LIB_OBJS += read-cache.o\n>>  LIB_OBJS += reflog-walk.o\n>> +LIB_OBJS += refs.o\n>>  LIB_OBJS += refs-be-files.o\n>>  LIB_OBJS += remote.o\n>>  LIB_OBJS += replace_object.o\n>> diff --git a/refs.c b/refs.c\n>> new file mode 100644\n>> index 0000000..77492ff\n>> --- /dev/null\n>> +++ b/refs.c\n>> @@ -0,0 +1,3 @@\n>> +/*\n>> + * Common refs code for all backends.\n>> + */\n"},{"id":"248355","messageId":"CAL=YDWkfZV0CQRRQM_GxZ0+cuxTdFyH=u-sXLGab5kLtVf5fhQ@mail.gmail.com","threadId":"37379","inReplyTo":"xmqq8umbgcd9.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH v3 19/23] refs-be-files.c: add a backend method structure with transaction functions","fromName":"Ronnie Sahlberg","fromEmail":"sahlberg@google.com","sentAt":"2014-08-26T22:34:19Z","receivedAt":"2014-08-26T22:34:19Z","isPatch":true,"sender":{"key":"sahlberg@google.com","avatar":"https://avatars.githubusercontent.com/u/7320636?v=4"},"body":"On Tue, Aug 26, 2014 at 2:38 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Ronnie Sahlberg <sahlberg@google.com> writes:\n>\n>> diff --git a/refs-be-files.c b/refs-be-files.c\n>> index e58a7e1..27eafd0 100644\n>> --- a/refs-be-files.c\n>> +++ b/refs-be-files.c\n>> ...\n>> +struct ref_be refs_files = {\n>> +     files_transaction_begin,\n>> +     files_transaction_update_sha1,\n>> +     files_transaction_create_sha1,\n>> +     files_transaction_delete_sha1,\n>> +     files_transaction_update_reflog,\n>> +     files_transaction_commit,\n>> +     files_transaction_free,\n>> +};\n>> +\n>> +struct ref_be *refs = &refs_files;\n>\n>> diff --git a/refs.c b/refs.c\n>> index 6b434ad..b8c942f 100644\n>> --- a/refs.c\n>> +++ b/refs.c\n>> ...\n>> +void transaction_free(struct ref_transaction *transaction)\n>> +{\n>> +     return refs->transaction_free(transaction);\n>> +}\n>> diff --git a/refs.h b/refs.h\n>> index a14fc5d..4b669f5 100644\n>> --- a/refs.h\n>> +++ b/refs.h\n>> ...\n>> +struct ref_be {\n>> +     transaction_begin_fn transaction_begin;\n>> +     transaction_update_sha1_fn transaction_update_sha1;\n>> +     transaction_create_sha1_fn transaction_create_sha1;\n>> +     transaction_delete_sha1_fn transaction_delete_sha1;\n>> +     transaction_update_reflog_fn transaction_update_reflog;\n>> +     transaction_commit_fn transaction_commit;\n>> +     transaction_free_fn transaction_free;\n>> +};\n>> +\n>> +extern struct ref_be *refs;\n>> +\n>>  #endif /* REFS_H */\n>\n> The overall structure is certainly nice, but this means you only can\n> LINK with one backend.  Is that what we really want?\n>\n> I would have expected something like this:\n>\n>   * In refs.c, there is a \"static struct ref_be *the_refs_backend\"\n>     that points at the chosen singleton backend;\n\nDone.\nIt is also initialized to default to the files backend :\nrefs.c:\n\n  /* We always have a files backend and it is the default */\n  struct ref_be *the_refs_backend = &refs_be_files;\n\n\nThis does make \"refs_be_files\" and later \"refs_be_db\" public symbols instead of\nthe singleton. But we probably want/need these structures to be public anyway\nif we at some stage want to be able to switch between backends at runtime.\nrefs.h:\n\n   extern struct ref_be refs_be_files;\n   void set_refs_backend(struct ref_be *ref_be);\n\nThus allowing us to\n   set_refs_backend(&refs_be_files) to switch back to the files backend.\n\n\n\n\n>\n>   * Upon start-up, set_refs_backend() function that is exported from\n>     refs.c can be used to set the_refs_backend;\n>\n>   * Each refs-be-frotz.c will export \"struct ref_be refs_frotz\" (or\n>     perhaps \"struct refs_be refs_be_frotz\") to the outside world, so\n>     that the start-up code can call set_refs_backend() with it.\n\nYepp.\nrefs-be-db.c: does this.\n\n>\n>   * It is probably sensible to keep the_refs_backend default to\n>     &refs_be_files.\n>\n\nYepp.\n\nhttps://github.com/rsahlberg/git/tree/backend-struct-db\nhttps://github.com/rsahlberg/git/tree/backend-struct-db-2 (adds a db\nbackend and daemon)\n\n\nThanks. Good suggestions.\n"}]}