* [PATCH v2 27/38] lock_ref_for_update(): add a files_ref_store argument
From: Michael Haggerty @ 2016-09-04 16:08 UTC (permalink / raw)
To: Junio C Hamano
Cc: David Turner, Ramsay Jones, Eric Sunshine, Jeff King,
Nguyễn Thái Ngọc Duy, git, Michael Haggerty
In-Reply-To: <cover.1473003902.git.mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs/files-backend.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 001b8ef..2f8eb54 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -3514,20 +3514,21 @@ static int check_old_oid(struct ref_update *update, struct object_id *oid,
* - If it is an update of head_ref, add a corresponding REF_LOG_ONLY
* update of HEAD.
*/
-static int lock_ref_for_update(struct ref_update *update,
+static int lock_ref_for_update(struct files_ref_store *refs,
+ struct ref_update *update,
struct ref_transaction *transaction,
const char *head_ref,
struct string_list *affected_refnames,
struct strbuf *err)
{
- struct files_ref_store *refs =
- get_files_ref_store(NULL, "lock_ref_for_update");
struct strbuf referent = STRBUF_INIT;
int mustexist = (update->flags & REF_HAVE_OLD) &&
!is_null_sha1(update->old_sha1);
int ret;
struct ref_lock *lock;
+ assert_main_repository(&refs->base, "lock_ref_for_update");
+
if ((update->flags & REF_HAVE_NEW) && is_null_sha1(update->new_sha1))
update->flags |= REF_DELETING;
@@ -3730,8 +3731,8 @@ static int files_transaction_commit(struct ref_store *ref_store,
for (i = 0; i < transaction->nr; i++) {
struct ref_update *update = transaction->updates[i];
- ret = lock_ref_for_update(update, transaction, head_ref,
- &affected_refnames, err);
+ ret = lock_ref_for_update(refs, update, transaction,
+ head_ref, &affected_refnames, err);
if (ret)
goto cleanup;
}
--
2.9.3
^ permalink raw reply related
* [PATCH v2 26/38] commit_ref_update(): add a files_ref_store argument
From: Michael Haggerty @ 2016-09-04 16:08 UTC (permalink / raw)
To: Junio C Hamano
Cc: David Turner, Ramsay Jones, Eric Sunshine, Jeff King,
Nguyễn Thái Ngọc Duy, git, Michael Haggerty
In-Reply-To: <cover.1473003902.git.mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs/files-backend.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index ae425c5..001b8ef 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -2574,12 +2574,14 @@ static int files_verify_refname_available(struct ref_store *ref_store,
static int write_ref_to_lockfile(struct ref_lock *lock,
const unsigned char *sha1, struct strbuf *err);
-static int commit_ref_update(struct ref_lock *lock,
+static int commit_ref_update(struct files_ref_store *refs,
+ struct ref_lock *lock,
const unsigned char *sha1, const char *logmsg,
struct strbuf *err);
int rename_ref(const char *oldrefname, const char *newrefname, const char *logmsg)
{
+ struct files_ref_store *refs = get_files_ref_store(NULL, "rename_ref");
unsigned char sha1[20], orig_sha1[20];
int flag = 0, logmoved = 0;
struct ref_lock *lock;
@@ -2652,7 +2654,7 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
hashcpy(lock->old_oid.hash, orig_sha1);
if (write_ref_to_lockfile(lock, orig_sha1, &err) ||
- commit_ref_update(lock, orig_sha1, logmsg, &err)) {
+ commit_ref_update(refs, lock, orig_sha1, logmsg, &err)) {
error("unable to write current sha1 into %s: %s", newrefname, err.buf);
strbuf_release(&err);
goto rollback;
@@ -2672,7 +2674,7 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
flag = log_all_ref_updates;
log_all_ref_updates = 0;
if (write_ref_to_lockfile(lock, orig_sha1, &err) ||
- commit_ref_update(lock, orig_sha1, NULL, &err)) {
+ commit_ref_update(refs, lock, orig_sha1, NULL, &err)) {
error("unable to write current sha1 into %s: %s", oldrefname, err.buf);
strbuf_release(&err);
}
@@ -2908,12 +2910,12 @@ static int write_ref_to_lockfile(struct ref_lock *lock,
* to the loose reference lockfile. Also update the reflogs if
* necessary, using the specified lockmsg (which can be NULL).
*/
-static int commit_ref_update(struct ref_lock *lock,
+static int commit_ref_update(struct files_ref_store *refs,
+ struct ref_lock *lock,
const unsigned char *sha1, const char *logmsg,
struct strbuf *err)
{
- struct files_ref_store *refs =
- get_files_ref_store(NULL, "commit_ref_update");
+ assert_main_repository(&refs->base, "commit_ref_update");
clear_loose_ref_cache(refs);
if (log_ref_write(lock->ref_name, lock->old_oid.hash, sha1, logmsg, 0, err)) {
--
2.9.3
^ permalink raw reply related
* [PATCH v2 15/38] resolve_ref_recursively(): new function
From: Michael Haggerty @ 2016-09-04 16:08 UTC (permalink / raw)
To: Junio C Hamano
Cc: David Turner, Ramsay Jones, Eric Sunshine, Jeff King,
Nguyễn Thái Ngọc Duy, git, Michael Haggerty
In-Reply-To: <cover.1473003902.git.mhagger@alum.mit.edu>
Add a new function, resolve_ref_recursively(), which is basically like
the old resolve_ref_unsafe() except that it takes a (ref_store *)
argument and also works for submodules.
Re-implement resolve_ref_unsafe() as a thin wrapper around
resolve_ref_recursively().
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/refs.c b/refs.c
index 9e6b005..3723169 100644
--- a/refs.c
+++ b/refs.c
@@ -1216,13 +1216,14 @@ int for_each_rawref(each_ref_fn fn, void *cb_data)
}
/* This function needs to return a meaningful errno on failure */
-const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
- unsigned char *sha1, int *flags)
+static const char *resolve_ref_recursively(struct ref_store *refs,
+ const char *refname,
+ int resolve_flags,
+ unsigned char *sha1, int *flags)
{
static struct strbuf sb_refname = STRBUF_INIT;
int unused_flags;
int symref_count;
- struct ref_store *refs = get_ref_store(NULL);
if (!flags)
flags = &unused_flags;
@@ -1291,6 +1292,13 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
return NULL;
}
+const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
+ unsigned char *sha1, int *flags)
+{
+ return resolve_ref_recursively(get_ref_store(NULL), refname,
+ resolve_flags, sha1, flags);
+}
+
/* A pointer to the ref_store for the main repository: */
static struct ref_store *main_ref_store;
--
2.9.3
^ permalink raw reply related
* [PATCH v2 36/38] refs: add method to rename refs
From: Michael Haggerty @ 2016-09-04 16:08 UTC (permalink / raw)
To: Junio C Hamano
Cc: David Turner, Ramsay Jones, Eric Sunshine, Jeff King,
Nguyễn Thái Ngọc Duy, git, David Turner,
Michael Haggerty
In-Reply-To: <cover.1473003902.git.mhagger@alum.mit.edu>
From: David Turner <dturner@twopensource.com>
This removes the last caller of function get_files_ref_store(), so
remove it.
Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs.c | 7 +++++++
refs/files-backend.c | 24 ++++++------------------
refs/refs-internal.h | 4 ++++
3 files changed, 17 insertions(+), 18 deletions(-)
diff --git a/refs.c b/refs.c
index fcaf3ba..113e3c8 100644
--- a/refs.c
+++ b/refs.c
@@ -1547,3 +1547,10 @@ int delete_refs(struct string_list *refnames, unsigned int flags)
return refs->be->delete_refs(refs, refnames, flags);
}
+
+int rename_ref(const char *oldref, const char *newref, const char *logmsg)
+{
+ struct ref_store *refs = get_ref_store(NULL);
+
+ return refs->be->rename_ref(refs, oldref, newref, logmsg);
+}
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 56397af..7cc4191 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -997,22 +997,6 @@ static struct files_ref_store *files_downcast(
return (struct files_ref_store *)ref_store;
}
-/*
- * Return a pointer to the reference store for the specified
- * submodule. For the main repository, use submodule==NULL; such a
- * call cannot fail. For a submodule, the submodule must exist and be
- * a nonbare repository, otherwise return NULL. Verify that the
- * reference store is a files_ref_store, and cast it to that type
- * before returning it.
- */
-static struct files_ref_store *get_files_ref_store(const char *submodule,
- const char *caller)
-{
- struct ref_store *refs = get_ref_store(submodule);
-
- return refs ? files_downcast(refs, 1, caller) : NULL;
-}
-
/* The length of a peeled reference line in packed-refs, including EOL: */
#define PEELED_LINE_LENGTH 42
@@ -2580,9 +2564,12 @@ static int commit_ref_update(struct files_ref_store *refs,
const unsigned char *sha1, const char *logmsg,
struct strbuf *err);
-int rename_ref(const char *oldrefname, const char *newrefname, const char *logmsg)
+static int files_rename_ref(struct ref_store *ref_store,
+ const char *oldrefname, const char *newrefname,
+ const char *logmsg)
{
- struct files_ref_store *refs = get_files_ref_store(NULL, "rename_ref");
+ struct files_ref_store *refs =
+ files_downcast(ref_store, 0, "rename_ref");
unsigned char sha1[20], orig_sha1[20];
int flag = 0, logmoved = 0;
struct ref_lock *lock;
@@ -4097,6 +4084,7 @@ struct ref_storage_be refs_be_files = {
files_peel_ref,
files_create_symref,
files_delete_refs,
+ files_rename_ref,
files_ref_iterator_begin,
files_read_raw_ref,
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index b3a2095..c598cb1 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -494,6 +494,9 @@ typedef int create_symref_fn(struct ref_store *ref_store,
const char *logmsg);
typedef int delete_refs_fn(struct ref_store *ref_store,
struct string_list *refnames, unsigned int flags);
+typedef int rename_ref_fn(struct ref_store *ref_store,
+ const char *oldref, const char *newref,
+ const char *logmsg);
/*
* Iterate over the references in the specified ref_store that are
@@ -593,6 +596,7 @@ struct ref_storage_be {
peel_ref_fn *peel_ref;
create_symref_fn *create_symref;
delete_refs_fn *delete_refs;
+ rename_ref_fn *rename_ref;
ref_iterator_begin_fn *iterator_begin;
read_raw_ref_fn *read_raw_ref;
--
2.9.3
^ permalink raw reply related
* [PATCH v2 28/38] lock_ref_sha1_basic(): add a files_ref_store argument
From: Michael Haggerty @ 2016-09-04 16:08 UTC (permalink / raw)
To: Junio C Hamano
Cc: David Turner, Ramsay Jones, Eric Sunshine, Jeff King,
Nguyễn Thái Ngọc Duy, git, Michael Haggerty
In-Reply-To: <cover.1473003902.git.mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs/files-backend.c | 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 2f8eb54..ab2c1de 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1983,15 +1983,14 @@ static int remove_empty_directories(struct strbuf *path)
* Locks a ref returning the lock on success and NULL on failure.
* On failure errno is set to something meaningful.
*/
-static struct ref_lock *lock_ref_sha1_basic(const char *refname,
+static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs,
+ const char *refname,
const unsigned char *old_sha1,
const struct string_list *extras,
const struct string_list *skip,
unsigned int flags, int *type,
struct strbuf *err)
{
- struct files_ref_store *refs =
- get_files_ref_store(NULL, "lock_ref_sha1_basic");
struct strbuf ref_file = STRBUF_INIT;
struct ref_lock *lock;
int last_errno = 0;
@@ -2001,6 +2000,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
int attempts_remaining = 3;
int resolved;
+ assert_main_repository(&refs->base, "lock_ref_sha1_basic");
assert(err);
lock = xcalloc(1, sizeof(struct ref_lock));
@@ -2644,8 +2644,8 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
logmoved = log;
- lock = lock_ref_sha1_basic(newrefname, NULL, NULL, NULL, REF_NODEREF,
- NULL, &err);
+ lock = lock_ref_sha1_basic(refs, newrefname, NULL, NULL, NULL,
+ REF_NODEREF, NULL, &err);
if (!lock) {
error("unable to rename '%s' to '%s': %s", oldrefname, newrefname, err.buf);
strbuf_release(&err);
@@ -2663,8 +2663,8 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
return 0;
rollback:
- lock = lock_ref_sha1_basic(oldrefname, NULL, NULL, NULL, REF_NODEREF,
- NULL, &err);
+ lock = lock_ref_sha1_basic(refs, oldrefname, NULL, NULL, NULL,
+ REF_NODEREF, NULL, &err);
if (!lock) {
error("unable to lock %s for rollback: %s", oldrefname, err.buf);
strbuf_release(&err);
@@ -3020,13 +3020,14 @@ static int files_create_symref(struct ref_store *ref_store,
const char *refname, const char *target,
const char *logmsg)
{
+ struct files_ref_store *refs =
+ files_downcast(ref_store, 0, "create_symref");
struct strbuf err = STRBUF_INIT;
struct ref_lock *lock;
int ret;
- files_downcast(ref_store, 0, "create_symref");
-
- lock = lock_ref_sha1_basic(refname, NULL, NULL, NULL, REF_NODEREF, NULL,
+ lock = lock_ref_sha1_basic(refs, refname, NULL,
+ NULL, NULL, REF_NODEREF, NULL,
&err);
if (!lock) {
error("%s", err.buf);
@@ -3939,6 +3940,8 @@ int reflog_expire(const char *refname, const unsigned char *sha1,
reflog_expiry_cleanup_fn cleanup_fn,
void *policy_cb_data)
{
+ struct files_ref_store *refs =
+ get_files_ref_store(NULL, "reflog_expire");
static struct lock_file reflog_lock;
struct expire_reflog_cb cb;
struct ref_lock *lock;
@@ -3957,7 +3960,8 @@ int reflog_expire(const char *refname, const unsigned char *sha1,
* reference itself, plus we might need to update the
* reference if --updateref was specified:
*/
- lock = lock_ref_sha1_basic(refname, sha1, NULL, NULL, REF_NODEREF,
+ lock = lock_ref_sha1_basic(refs, refname, sha1,
+ NULL, NULL, REF_NODEREF,
&type, &err);
if (!lock) {
error("cannot lock ref '%s': %s", refname, err.buf);
--
2.9.3
^ permalink raw reply related
* [PATCH v2 34/38] refs: make delete_refs() virtual
From: Michael Haggerty @ 2016-09-04 16:08 UTC (permalink / raw)
To: Junio C Hamano
Cc: David Turner, Ramsay Jones, Eric Sunshine, Jeff King,
Nguyễn Thái Ngọc Duy, git, David Turner,
Michael Haggerty
In-Reply-To: <cover.1473003902.git.mhagger@alum.mit.edu>
From: David Turner <dturner@twopensource.com>
In the file-based backend, delete_refs has some special optimization
to deal with packed refs. In other backends, we might be able to make
ref deletion faster by putting all deletions into a single
transaction. So we need a special backend function for this.
Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs.c | 7 +++++++
refs/files-backend.c | 6 ++++--
refs/refs-internal.h | 3 +++
3 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/refs.c b/refs.c
index 3830918..6efa859 100644
--- a/refs.c
+++ b/refs.c
@@ -1532,3 +1532,10 @@ int initial_ref_transaction_commit(struct ref_transaction *transaction,
return refs->be->initial_transaction_commit(refs, transaction, err);
}
+
+int delete_refs(struct string_list *refnames, unsigned int flags)
+{
+ struct ref_store *refs = get_ref_store(NULL);
+
+ return refs->be->delete_refs(refs, refnames, flags);
+}
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 81008d7..bcaa958 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -2451,10 +2451,11 @@ static int delete_ref_loose(struct ref_lock *lock, int flag, struct strbuf *err)
return 0;
}
-int delete_refs(struct string_list *refnames, unsigned int flags)
+static int files_delete_refs(struct ref_store *ref_store,
+ struct string_list *refnames, unsigned int flags)
{
struct files_ref_store *refs =
- get_files_ref_store(NULL, "delete_refs");
+ files_downcast(ref_store, 0, "delete_refs");
struct strbuf err = STRBUF_INIT;
int i, result = 0;
@@ -4077,6 +4078,7 @@ struct ref_storage_be refs_be_files = {
files_pack_refs,
files_peel_ref,
files_create_symref,
+ files_delete_refs,
files_ref_iterator_begin,
files_read_raw_ref,
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index 08c8586..ade6501 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -490,6 +490,8 @@ typedef int create_symref_fn(struct ref_store *ref_store,
const char *ref_target,
const char *refs_heads_master,
const char *logmsg);
+typedef int delete_refs_fn(struct ref_store *ref_store,
+ struct string_list *refnames, unsigned int flags);
/*
* Iterate over the references in the specified ref_store that are
@@ -587,6 +589,7 @@ struct ref_storage_be {
pack_refs_fn *pack_refs;
peel_ref_fn *peel_ref;
create_symref_fn *create_symref;
+ delete_refs_fn *delete_refs;
ref_iterator_begin_fn *iterator_begin;
read_raw_ref_fn *read_raw_ref;
--
2.9.3
^ permalink raw reply related
* [PATCH v2 12/38] resolve_packed_ref(): rename function from resolve_missing_loose_ref()
From: Michael Haggerty @ 2016-09-04 16:08 UTC (permalink / raw)
To: Junio C Hamano
Cc: David Turner, Ramsay Jones, Eric Sunshine, Jeff King,
Nguyễn Thái Ngọc Duy, git, Michael Haggerty
In-Reply-To: <cover.1473003902.git.mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs/files-backend.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 7673342..32ca5ff 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1329,10 +1329,9 @@ static struct ref_entry *get_packed_ref(struct files_ref_store *refs,
/*
* A loose ref file doesn't exist; check for a packed ref.
*/
-static int resolve_missing_loose_ref(struct files_ref_store *refs,
- const char *refname,
- unsigned char *sha1,
- unsigned int *flags)
+static int resolve_packed_ref(struct files_ref_store *refs,
+ const char *refname,
+ unsigned char *sha1, unsigned int *flags)
{
struct ref_entry *entry;
@@ -1383,7 +1382,7 @@ int read_raw_ref(const char *refname, unsigned char *sha1,
if (lstat(path, &st) < 0) {
if (errno != ENOENT)
goto out;
- if (resolve_missing_loose_ref(refs, refname, sha1, type)) {
+ if (resolve_packed_ref(refs, refname, sha1, type)) {
errno = ENOENT;
goto out;
}
@@ -1417,7 +1416,7 @@ int read_raw_ref(const char *refname, unsigned char *sha1,
* ref is supposed to be, there could still be a
* packed ref:
*/
- if (resolve_missing_loose_ref(refs, refname, sha1, type)) {
+ if (resolve_packed_ref(refs, refname, sha1, type)) {
errno = EISDIR;
goto out;
}
--
2.9.3
^ permalink raw reply related
* [PATCH v2 13/38] resolve_gitlink_packed_ref(): remove function
From: Michael Haggerty @ 2016-09-04 16:08 UTC (permalink / raw)
To: Junio C Hamano
Cc: David Turner, Ramsay Jones, Eric Sunshine, Jeff King,
Nguyễn Thái Ngọc Duy, git, Michael Haggerty
In-Reply-To: <cover.1473003902.git.mhagger@alum.mit.edu>
Now that resolve_packed_ref() can work with an arbitrary
files_ref_store, there is no need to have a separate
resolve_gitlink_packed_ref() function.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs/files-backend.c | 26 +++++---------------------
1 file changed, 5 insertions(+), 21 deletions(-)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 32ca5ff..3b0c837 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1490,25 +1490,6 @@ static void unlock_ref(struct ref_lock *lock)
#define MAXREFLEN (1024)
-/*
- * Called by resolve_gitlink_ref_recursive() after it failed to read
- * from the loose refs in refs. Find <refname> in the packed-refs file
- * for the submodule.
- */
-static int resolve_gitlink_packed_ref(struct files_ref_store *refs,
- const char *refname, unsigned char *sha1)
-{
- struct ref_entry *ref;
- struct ref_dir *dir = get_packed_refs(refs);
-
- ref = find_ref(dir, refname);
- if (ref == NULL)
- return -1;
-
- hashcpy(sha1, ref->u.value.oid.hash);
- return 0;
-}
-
static int resolve_gitlink_ref_recursive(struct files_ref_store *refs,
const char *refname, unsigned char *sha1,
int recursion)
@@ -1524,8 +1505,11 @@ static int resolve_gitlink_ref_recursive(struct files_ref_store *refs,
: git_pathdup("%s", refname);
fd = open(path, O_RDONLY);
free(path);
- if (fd < 0)
- return resolve_gitlink_packed_ref(refs, refname, sha1);
+ if (fd < 0) {
+ unsigned int flags;
+
+ return resolve_packed_ref(refs, refname, sha1, &flags);
+ }
len = read(fd, buffer, sizeof(buffer)-1);
close(fd);
--
2.9.3
^ permalink raw reply related
* [PATCH v2 19/38] refs: make read_raw_ref() virtual
From: Michael Haggerty @ 2016-09-04 16:08 UTC (permalink / raw)
To: Junio C Hamano
Cc: David Turner, Ramsay Jones, Eric Sunshine, Jeff King,
Nguyễn Thái Ngọc Duy, git, Michael Haggerty
In-Reply-To: <cover.1473003902.git.mhagger@alum.mit.edu>
Reference backends will be able to customize this function to implement
reference reading.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs.c | 4 ++--
refs/files-backend.c | 14 ++++++++------
refs/refs-internal.h | 36 +++++++++++++++++++-----------------
3 files changed, 29 insertions(+), 25 deletions(-)
diff --git a/refs.c b/refs.c
index e881874..7a7adeb 100644
--- a/refs.c
+++ b/refs.c
@@ -1251,8 +1251,8 @@ static const char *resolve_ref_recursively(struct ref_store *refs,
for (symref_count = 0; symref_count < SYMREF_MAXDEPTH; symref_count++) {
unsigned int read_flags = 0;
- if (read_raw_ref(refs, refname,
- sha1, &sb_refname, &read_flags)) {
+ if (refs->be->read_raw_ref(refs, refname,
+ sha1, &sb_refname, &read_flags)) {
*flags |= read_flags;
if (errno != ENOENT || (resolve_flags & RESOLVE_REF_READING))
return NULL;
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 6382c6b..ff11a51 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1349,9 +1349,9 @@ static int resolve_packed_ref(struct files_ref_store *refs,
return -1;
}
-int read_raw_ref(struct ref_store *ref_store,
- const char *refname, unsigned char *sha1,
- struct strbuf *referent, unsigned int *type)
+static int files_read_raw_ref(struct ref_store *ref_store,
+ const char *refname, unsigned char *sha1,
+ struct strbuf *referent, unsigned int *type)
{
struct files_ref_store *refs =
files_downcast(ref_store, 1, "read_raw_ref");
@@ -1623,8 +1623,8 @@ static int lock_raw_ref(const char *refname, int mustexist,
* fear that its value will change.
*/
- if (read_raw_ref(ref_store, refname,
- lock->old_oid.hash, referent, type)) {
+ if (files_read_raw_ref(ref_store, refname,
+ lock->old_oid.hash, referent, type)) {
if (errno == ENOENT) {
if (mustexist) {
/* Garden variety missing reference. */
@@ -4029,5 +4029,7 @@ struct ref_storage_be refs_be_files = {
NULL,
"files",
files_ref_store_create,
- files_transaction_commit
+ files_transaction_commit,
+
+ files_read_raw_ref
};
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index fa41d51..19cb6e1 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -486,6 +486,20 @@ int do_for_each_ref_iterator(struct ref_iterator *iter,
struct ref_store;
+/* refs backends */
+
+/*
+ * Initialize the ref_store for the specified submodule, or for the
+ * main repository if submodule == NULL. These functions should call
+ * base_ref_store_init() to initialize the shared part of the
+ * ref_store and to record the ref_store for later lookup.
+ */
+typedef struct ref_store *ref_store_init_fn(const char *submodule);
+
+typedef int ref_transaction_commit_fn(struct ref_store *refs,
+ struct ref_transaction *transaction,
+ struct strbuf *err);
+
/*
* Read a reference from the specified reference store, non-recursively.
* Set type to describe the reference, and:
@@ -524,29 +538,17 @@ struct ref_store;
* - in all other cases, referent will be untouched, and therefore
* refname will still be valid and unchanged.
*/
-int read_raw_ref(struct ref_store *ref_store,
- const char *refname, unsigned char *sha1,
- struct strbuf *referent, unsigned int *type);
-
-/* refs backends */
-
-/*
- * Initialize the ref_store for the specified submodule, or for the
- * main repository if submodule == NULL. These functions should call
- * base_ref_store_init() to initialize the shared part of the
- * ref_store and to record the ref_store for later lookup.
- */
-typedef struct ref_store *ref_store_init_fn(const char *submodule);
-
-typedef int ref_transaction_commit_fn(struct ref_store *refs,
- struct ref_transaction *transaction,
- struct strbuf *err);
+typedef int read_raw_ref_fn(struct ref_store *ref_store,
+ const char *refname, unsigned char *sha1,
+ struct strbuf *referent, unsigned int *type);
struct ref_storage_be {
struct ref_storage_be *next;
const char *name;
ref_store_init_fn *init;
ref_transaction_commit_fn *transaction_commit;
+
+ read_raw_ref_fn *read_raw_ref;
};
extern struct ref_storage_be refs_be_files;
--
2.9.3
^ permalink raw reply related
* [PATCH v2 25/38] lock_raw_ref(): add a files_ref_store argument
From: Michael Haggerty @ 2016-09-04 16:08 UTC (permalink / raw)
To: Junio C Hamano
Cc: David Turner, Ramsay Jones, Eric Sunshine, Jeff King,
Nguyễn Thái Ngọc Duy, git, Michael Haggerty
In-Reply-To: <cover.1473003902.git.mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs/files-backend.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 363f306..ae425c5 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1523,7 +1523,8 @@ static void unlock_ref(struct ref_lock *lock)
* avoided, namely if we were successfully able to read the ref
* - Generate informative error messages in the case of failure
*/
-static int lock_raw_ref(const char *refname, int mustexist,
+static int lock_raw_ref(struct files_ref_store *refs,
+ const char *refname, int mustexist,
const struct string_list *extras,
const struct string_list *skip,
struct ref_lock **lock_p,
@@ -1531,15 +1532,14 @@ static int lock_raw_ref(const char *refname, int mustexist,
unsigned int *type,
struct strbuf *err)
{
- struct ref_store *ref_store = get_ref_store(NULL);
- struct files_ref_store *refs =
- files_downcast(ref_store, 0, "lock_raw_ref");
struct ref_lock *lock;
struct strbuf ref_file = STRBUF_INIT;
int attempts_remaining = 3;
int ret = TRANSACTION_GENERIC_ERROR;
assert(err);
+ assert_main_repository(&refs->base, "lock_raw_ref");
+
*type = 0;
/* First lock the file so it can't change out from under us. */
@@ -1623,7 +1623,7 @@ static int lock_raw_ref(const char *refname, int mustexist,
* fear that its value will change.
*/
- if (files_read_raw_ref(ref_store, refname,
+ if (files_read_raw_ref(&refs->base, refname,
lock->old_oid.hash, referent, type)) {
if (errno == ENOENT) {
if (mustexist) {
@@ -3518,6 +3518,8 @@ static int lock_ref_for_update(struct ref_update *update,
struct string_list *affected_refnames,
struct strbuf *err)
{
+ struct files_ref_store *refs =
+ get_files_ref_store(NULL, "lock_ref_for_update");
struct strbuf referent = STRBUF_INIT;
int mustexist = (update->flags & REF_HAVE_OLD) &&
!is_null_sha1(update->old_sha1);
@@ -3534,7 +3536,7 @@ static int lock_ref_for_update(struct ref_update *update,
return ret;
}
- ret = lock_raw_ref(update->refname, mustexist,
+ ret = lock_raw_ref(refs, update->refname, mustexist,
affected_refnames, NULL,
&update->lock, &referent,
&update->type, err);
--
2.9.3
^ permalink raw reply related
* [PATCH v2 11/38] refs: reorder definitions
From: Michael Haggerty @ 2016-09-04 16:08 UTC (permalink / raw)
To: Junio C Hamano
Cc: David Turner, Ramsay Jones, Eric Sunshine, Jeff King,
Nguyễn Thái Ngọc Duy, git, Michael Haggerty
In-Reply-To: <cover.1473003902.git.mhagger@alum.mit.edu>
Move resolve_gitlink_ref() and related functions lower in the file to
avoid the need for forward declarations in the next step.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs/files-backend.c | 166 +++++++++++++++++++++++++--------------------------
1 file changed, 83 insertions(+), 83 deletions(-)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index d896052..7673342 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1316,89 +1316,6 @@ static struct ref_dir *get_loose_refs(struct files_ref_store *refs)
return get_ref_dir(refs->loose);
}
-#define MAXREFLEN (1024)
-
-/*
- * Called by resolve_gitlink_ref_recursive() after it failed to read
- * from the loose refs in refs. Find <refname> in the packed-refs file
- * for the submodule.
- */
-static int resolve_gitlink_packed_ref(struct files_ref_store *refs,
- const char *refname, unsigned char *sha1)
-{
- struct ref_entry *ref;
- struct ref_dir *dir = get_packed_refs(refs);
-
- ref = find_ref(dir, refname);
- if (ref == NULL)
- return -1;
-
- hashcpy(sha1, ref->u.value.oid.hash);
- return 0;
-}
-
-static int resolve_gitlink_ref_recursive(struct files_ref_store *refs,
- const char *refname, unsigned char *sha1,
- int recursion)
-{
- int fd, len;
- char buffer[128], *p;
- char *path;
-
- if (recursion > SYMREF_MAXDEPTH || strlen(refname) > MAXREFLEN)
- return -1;
- path = *refs->base.submodule
- ? git_pathdup_submodule(refs->base.submodule, "%s", refname)
- : git_pathdup("%s", refname);
- fd = open(path, O_RDONLY);
- free(path);
- if (fd < 0)
- return resolve_gitlink_packed_ref(refs, refname, sha1);
-
- len = read(fd, buffer, sizeof(buffer)-1);
- close(fd);
- if (len < 0)
- return -1;
- while (len && isspace(buffer[len-1]))
- len--;
- buffer[len] = 0;
-
- /* Was it a detached head or an old-fashioned symlink? */
- if (!get_sha1_hex(buffer, sha1))
- return 0;
-
- /* Symref? */
- if (strncmp(buffer, "ref:", 4))
- return -1;
- p = buffer + 4;
- while (isspace(*p))
- p++;
-
- return resolve_gitlink_ref_recursive(refs, p, sha1, recursion+1);
-}
-
-int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *sha1)
-{
- int len = strlen(path);
- struct strbuf submodule = STRBUF_INIT;
- struct files_ref_store *refs;
-
- while (len && path[len-1] == '/')
- len--;
- if (!len)
- return -1;
-
- strbuf_add(&submodule, path, len);
- refs = get_files_ref_store(submodule.buf, "resolve_gitlink_ref");
- if (!refs) {
- strbuf_release(&submodule);
- return -1;
- }
- strbuf_release(&submodule);
-
- return resolve_gitlink_ref_recursive(refs, refname, sha1, 0);
-}
-
/*
* Return the ref_entry for the given refname from the packed
* references. If it does not exist, return NULL.
@@ -1572,6 +1489,89 @@ static void unlock_ref(struct ref_lock *lock)
free(lock);
}
+#define MAXREFLEN (1024)
+
+/*
+ * Called by resolve_gitlink_ref_recursive() after it failed to read
+ * from the loose refs in refs. Find <refname> in the packed-refs file
+ * for the submodule.
+ */
+static int resolve_gitlink_packed_ref(struct files_ref_store *refs,
+ const char *refname, unsigned char *sha1)
+{
+ struct ref_entry *ref;
+ struct ref_dir *dir = get_packed_refs(refs);
+
+ ref = find_ref(dir, refname);
+ if (ref == NULL)
+ return -1;
+
+ hashcpy(sha1, ref->u.value.oid.hash);
+ return 0;
+}
+
+static int resolve_gitlink_ref_recursive(struct files_ref_store *refs,
+ const char *refname, unsigned char *sha1,
+ int recursion)
+{
+ int fd, len;
+ char buffer[128], *p;
+ char *path;
+
+ if (recursion > SYMREF_MAXDEPTH || strlen(refname) > MAXREFLEN)
+ return -1;
+ path = *refs->base.submodule
+ ? git_pathdup_submodule(refs->base.submodule, "%s", refname)
+ : git_pathdup("%s", refname);
+ fd = open(path, O_RDONLY);
+ free(path);
+ if (fd < 0)
+ return resolve_gitlink_packed_ref(refs, refname, sha1);
+
+ len = read(fd, buffer, sizeof(buffer)-1);
+ close(fd);
+ if (len < 0)
+ return -1;
+ while (len && isspace(buffer[len-1]))
+ len--;
+ buffer[len] = 0;
+
+ /* Was it a detached head or an old-fashioned symlink? */
+ if (!get_sha1_hex(buffer, sha1))
+ return 0;
+
+ /* Symref? */
+ if (strncmp(buffer, "ref:", 4))
+ return -1;
+ p = buffer + 4;
+ while (isspace(*p))
+ p++;
+
+ return resolve_gitlink_ref_recursive(refs, p, sha1, recursion+1);
+}
+
+int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *sha1)
+{
+ int len = strlen(path);
+ struct strbuf submodule = STRBUF_INIT;
+ struct files_ref_store *refs;
+
+ while (len && path[len-1] == '/')
+ len--;
+ if (!len)
+ return -1;
+
+ strbuf_add(&submodule, path, len);
+ refs = get_files_ref_store(submodule.buf, "resolve_gitlink_ref");
+ if (!refs) {
+ strbuf_release(&submodule);
+ return -1;
+ }
+ strbuf_release(&submodule);
+
+ return resolve_gitlink_ref_recursive(refs, refname, sha1, 0);
+}
+
/*
* Lock refname, without following symrefs, and set *lock_p to point
* at a newly-allocated lock object. Fill in lock->old_oid, referent,
--
2.9.3
^ permalink raw reply related
* [PATCH v2 17/38] resolve_gitlink_ref(): avoid memory allocation in many cases
From: Michael Haggerty @ 2016-09-04 16:08 UTC (permalink / raw)
To: Junio C Hamano
Cc: David Turner, Ramsay Jones, Eric Sunshine, Jeff King,
Nguyễn Thái Ngọc Duy, git, Michael Haggerty
In-Reply-To: <cover.1473003902.git.mhagger@alum.mit.edu>
If we don't have to strip trailing '/' from the submodule path, then
don't allocate and copy the submodule name.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/refs.c b/refs.c
index 647ead5..34c0c5e 100644
--- a/refs.c
+++ b/refs.c
@@ -1301,19 +1301,26 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *sha1)
{
- int len = strlen(path);
- struct strbuf submodule = STRBUF_INIT;
+ size_t len = strlen(path);
struct ref_store *refs;
int flags;
- while (len && path[len-1] == '/')
+ while (len && path[len - 1] == '/')
len--;
+
if (!len)
return -1;
- strbuf_add(&submodule, path, len);
- refs = get_ref_store(submodule.buf);
- strbuf_release(&submodule);
+ if (path[len]) {
+ /* We need to strip off one or more trailing slashes */
+ char *stripped = xmemdupz(path, len);
+
+ refs = get_ref_store(stripped);
+ free(stripped);
+ } else {
+ refs = get_ref_store(path);
+ }
+
if (!refs)
return -1;
--
2.9.3
^ permalink raw reply related
* [PATCH v2 24/38] repack_without_refs(): add a files_ref_store argument
From: Michael Haggerty @ 2016-09-04 16:08 UTC (permalink / raw)
To: Junio C Hamano
Cc: David Turner, Ramsay Jones, Eric Sunshine, Jeff King,
Nguyễn Thái Ngọc Duy, git, Michael Haggerty
In-Reply-To: <cover.1473003902.git.mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs/files-backend.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 8d43e0b..363f306 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -2384,14 +2384,14 @@ static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)
*
* The refs in 'refnames' needn't be sorted. `err` must not be NULL.
*/
-static int repack_without_refs(struct string_list *refnames, struct strbuf *err)
+static int repack_without_refs(struct files_ref_store *refs,
+ struct string_list *refnames, struct strbuf *err)
{
- struct files_ref_store *refs =
- get_files_ref_store(NULL, "repack_without_refs");
struct ref_dir *packed;
struct string_list_item *refname;
int ret, needs_repacking = 0, removed = 0;
+ assert_main_repository(&refs->base, "repack_without_refs");
assert(err);
/* Look for a packed ref */
@@ -2453,13 +2453,15 @@ static int delete_ref_loose(struct ref_lock *lock, int flag, struct strbuf *err)
int delete_refs(struct string_list *refnames, unsigned int flags)
{
+ struct files_ref_store *refs =
+ get_files_ref_store(NULL, "delete_refs");
struct strbuf err = STRBUF_INIT;
int i, result = 0;
if (!refnames->nr)
return 0;
- result = repack_without_refs(refnames, &err);
+ result = repack_without_refs(refs, refnames, &err);
if (result) {
/*
* If we failed to rewrite the packed-refs file, then
@@ -3779,7 +3781,7 @@ static int files_transaction_commit(struct ref_store *ref_store,
}
}
- if (repack_without_refs(&refs_to_delete, err)) {
+ if (repack_without_refs(refs, &refs_to_delete, err)) {
ret = TRANSACTION_GENERIC_ERROR;
goto cleanup;
}
--
2.9.3
^ permalink raw reply related
* [PATCH v2 20/38] refs: make verify_refname_available() virtual
From: Michael Haggerty @ 2016-09-04 16:08 UTC (permalink / raw)
To: Junio C Hamano
Cc: David Turner, Ramsay Jones, Eric Sunshine, Jeff King,
Nguyễn Thái Ngọc Duy, git, Michael Haggerty
In-Reply-To: <cover.1473003902.git.mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs.c | 10 ++++++++++
refs/files-backend.c | 14 ++++++++------
refs/refs-internal.h | 7 +++++++
3 files changed, 25 insertions(+), 6 deletions(-)
diff --git a/refs.c b/refs.c
index 7a7adeb..662c417 100644
--- a/refs.c
+++ b/refs.c
@@ -1428,3 +1428,13 @@ int ref_transaction_commit(struct ref_transaction *transaction,
return refs->be->transaction_commit(refs, transaction, err);
}
+
+int verify_refname_available(const char *refname,
+ const struct string_list *extra,
+ const struct string_list *skip,
+ struct strbuf *err)
+{
+ struct ref_store *refs = get_ref_store(NULL);
+
+ return refs->be->verify_refname_available(refs, refname, extra, skip, err);
+}
diff --git a/refs/files-backend.c b/refs/files-backend.c
index ff11a51..4e1d431 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -2549,13 +2549,14 @@ static int rename_tmp_log(const char *newrefname)
return ret;
}
-int verify_refname_available(const char *newname,
- const struct string_list *extras,
- const struct string_list *skip,
- struct strbuf *err)
+static int files_verify_refname_available(struct ref_store *ref_store,
+ const char *newname,
+ const struct string_list *extras,
+ const struct string_list *skip,
+ struct strbuf *err)
{
struct files_ref_store *refs =
- get_files_ref_store(NULL, "verify_refname_available");
+ files_downcast(ref_store, 1, "verify_refname_available");
struct ref_dir *packed_refs = get_packed_refs(refs);
struct ref_dir *loose_refs = get_loose_refs(refs);
@@ -4031,5 +4032,6 @@ struct ref_storage_be refs_be_files = {
files_ref_store_create,
files_transaction_commit,
- files_read_raw_ref
+ files_read_raw_ref,
+ files_verify_refname_available
};
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index 19cb6e1..6c698f4 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -542,6 +542,12 @@ typedef int read_raw_ref_fn(struct ref_store *ref_store,
const char *refname, unsigned char *sha1,
struct strbuf *referent, unsigned int *type);
+typedef int verify_refname_available_fn(struct ref_store *ref_store,
+ const char *newname,
+ const struct string_list *extras,
+ const struct string_list *skip,
+ struct strbuf *err);
+
struct ref_storage_be {
struct ref_storage_be *next;
const char *name;
@@ -549,6 +555,7 @@ struct ref_storage_be {
ref_transaction_commit_fn *transaction_commit;
read_raw_ref_fn *read_raw_ref;
+ verify_refname_available_fn *verify_refname_available;
};
extern struct ref_storage_be refs_be_files;
--
2.9.3
^ permalink raw reply related
* [PATCH v2 05/38] refs: create a base class "ref_store" for files_ref_store
From: Michael Haggerty @ 2016-09-04 16:08 UTC (permalink / raw)
To: Junio C Hamano
Cc: David Turner, Ramsay Jones, Eric Sunshine, Jeff King,
Nguyễn Thái Ngọc Duy, git, Michael Haggerty
In-Reply-To: <cover.1473003902.git.mhagger@alum.mit.edu>
We want ref_stores to be polymorphic, so invent a base class of which
files_ref_store is a derived class. For now there is exactly one
ref_store for the main repository and one for any submodules whose
references have been accessed.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs.c | 93 +++++++++++++++++++++++++++
refs/files-backend.c | 177 ++++++++++++++++++++++++++++-----------------------
refs/refs-internal.h | 78 +++++++++++++++++++++++
3 files changed, 270 insertions(+), 78 deletions(-)
diff --git a/refs.c b/refs.c
index d2a29bb..9d6bcb1 100644
--- a/refs.c
+++ b/refs.c
@@ -1151,8 +1151,12 @@ int head_ref(each_ref_fn fn, void *cb_data)
static int do_for_each_ref(const char *submodule, const char *prefix,
each_ref_fn fn, int trim, int flags, void *cb_data)
{
+ struct ref_store *refs = get_ref_store(submodule);
struct ref_iterator *iter;
+ if (!refs)
+ return 0;
+
iter = files_ref_iterator_begin(submodule, prefix, flags);
iter = prefix_ref_iterator_begin(iter, prefix, trim);
@@ -1284,3 +1288,92 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
errno = ELOOP;
return NULL;
}
+
+/* A pointer to the ref_store for the main repository: */
+static struct ref_store *main_ref_store;
+
+/* A linked list of ref_stores for submodules: */
+static struct ref_store *submodule_ref_stores;
+
+void base_ref_store_init(struct ref_store *refs,
+ const struct ref_storage_be *be,
+ const char *submodule)
+{
+ refs->be = be;
+ if (!submodule) {
+ if (main_ref_store)
+ die("BUG: main_ref_store initialized twice");
+
+ refs->submodule = "";
+ refs->next = NULL;
+ main_ref_store = refs;
+ } else {
+ if (lookup_ref_store(submodule))
+ die("BUG: ref_store for submodule '%s' initialized twice",
+ submodule);
+
+ refs->submodule = xstrdup(submodule);
+ refs->next = submodule_ref_stores;
+ submodule_ref_stores = refs;
+ }
+}
+
+struct ref_store *ref_store_init(const char *submodule)
+{
+ const char *be_name = "files";
+ struct ref_storage_be *be = find_ref_storage_backend(be_name);
+
+ if (!be)
+ die("BUG: reference backend %s is unknown", be_name);
+
+ if (!submodule || !*submodule)
+ return be->init(NULL);
+ else
+ return be->init(submodule);
+}
+
+struct ref_store *lookup_ref_store(const char *submodule)
+{
+ struct ref_store *refs;
+
+ if (!submodule || !*submodule)
+ return main_ref_store;
+
+ for (refs = submodule_ref_stores; refs; refs = refs->next) {
+ if (!strcmp(submodule, refs->submodule))
+ return refs;
+ }
+
+ return NULL;
+}
+
+struct ref_store *get_ref_store(const char *submodule)
+{
+ struct ref_store *refs;
+
+ if (!submodule || !*submodule) {
+ refs = lookup_ref_store(NULL);
+
+ if (!refs)
+ refs = ref_store_init(NULL);
+ } else {
+ refs = lookup_ref_store(submodule);
+
+ if (!refs) {
+ struct strbuf submodule_sb = STRBUF_INIT;
+
+ strbuf_addstr(&submodule_sb, submodule);
+ if (is_nonbare_repository_dir(&submodule_sb))
+ refs = ref_store_init(submodule);
+ strbuf_release(&submodule_sb);
+ }
+ }
+
+ return refs;
+}
+
+void assert_main_repository(struct ref_store *refs, const char *caller)
+{
+ if (*refs->submodule)
+ die("BUG: %s called for a submodule", caller);
+}
diff --git a/refs/files-backend.c b/refs/files-backend.c
index ecf66e6..439c500 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -910,17 +910,11 @@ struct packed_ref_cache {
* Future: need to be in "struct repository"
* when doing a full libification.
*/
-static struct files_ref_store {
- struct files_ref_store *next;
+struct files_ref_store {
+ struct ref_store base;
struct ref_entry *loose;
struct packed_ref_cache *packed;
- /*
- * The submodule name, or "" for the main repo. We allocate
- * length 1 rather than FLEX_ARRAY so that the main
- * files_ref_store is initialized correctly.
- */
- char name[1];
-} ref_store, *submodule_ref_stores;
+};
/* Lock used for the main packed-refs file: */
static struct lock_file packlock;
@@ -973,53 +967,50 @@ static void clear_loose_ref_cache(struct files_ref_store *refs)
* Create a new submodule ref cache and add it to the internal
* set of caches.
*/
-static struct files_ref_store *create_ref_store(const char *submodule)
+static struct ref_store *files_ref_store_create(const char *submodule)
{
- struct files_ref_store *refs;
- if (!submodule)
- submodule = "";
- FLEX_ALLOC_STR(refs, name, submodule);
- refs->next = submodule_ref_stores;
- submodule_ref_stores = refs;
- return refs;
+ struct files_ref_store *refs = xcalloc(1, sizeof(*refs));
+ struct ref_store *ref_store = (struct ref_store *)refs;
+
+ base_ref_store_init(ref_store, &refs_be_files, submodule);
+
+ return ref_store;
}
-static struct files_ref_store *lookup_ref_store(const char *submodule)
+/*
+ * Downcast ref_store to files_ref_store. Die if ref_store is not a
+ * files_ref_store. If submodule_allowed is not true, then also die if
+ * files_ref_store is for a submodule (i.e., not for the main
+ * repository). caller is used in any necessary error messages.
+ */
+static struct files_ref_store *files_downcast(
+ struct ref_store *ref_store, int submodule_allowed,
+ const char *caller)
{
- struct files_ref_store *refs;
+ if (ref_store->be != &refs_be_files)
+ die("BUG: ref_store is type \"%s\" not \"files\" in %s",
+ ref_store->be->name, caller);
- if (!submodule || !*submodule)
- return &ref_store;
+ if (!submodule_allowed)
+ assert_main_repository(ref_store, caller);
- for (refs = submodule_ref_stores; refs; refs = refs->next)
- if (!strcmp(submodule, refs->name))
- return refs;
- return NULL;
+ return (struct files_ref_store *)ref_store;
}
/*
- * Return a pointer to a files_ref_store for the specified submodule. For
- * the main repository, use submodule==NULL; such a call cannot fail.
- * For a submodule, the submodule must exist and be a nonbare
- * repository, otherwise return NULL.
- *
- * The returned structure will be allocated and initialized but not
- * necessarily populated; it should not be freed.
+ * Return a pointer to the reference store for the specified
+ * submodule. For the main repository, use submodule==NULL; such a
+ * call cannot fail. For a submodule, the submodule must exist and be
+ * a nonbare repository, otherwise return NULL. Verify that the
+ * reference store is a files_ref_store, and cast it to that type
+ * before returning it.
*/
-static struct files_ref_store *get_ref_store(const char *submodule)
+static struct files_ref_store *get_files_ref_store(const char *submodule,
+ const char *caller)
{
- struct files_ref_store *refs = lookup_ref_store(submodule);
+ struct ref_store *refs = get_ref_store(submodule);
- if (!refs) {
- struct strbuf submodule_sb = STRBUF_INIT;
-
- strbuf_addstr(&submodule_sb, submodule);
- if (is_nonbare_repository_dir(&submodule_sb))
- refs = create_ref_store(submodule);
- strbuf_release(&submodule_sb);
- }
-
- return refs;
+ return refs ? files_downcast(refs, 1, caller) : NULL;
}
/* The length of a peeled reference line in packed-refs, including EOL: */
@@ -1158,8 +1149,9 @@ static struct packed_ref_cache *get_packed_ref_cache(struct files_ref_store *ref
{
char *packed_refs_file;
- if (*refs->name)
- packed_refs_file = git_pathdup_submodule(refs->name, "packed-refs");
+ if (*refs->base.submodule)
+ packed_refs_file = git_pathdup_submodule(refs->base.submodule,
+ "packed-refs");
else
packed_refs_file = git_pathdup("packed-refs");
@@ -1202,8 +1194,9 @@ static struct ref_dir *get_packed_refs(struct files_ref_store *refs)
*/
static void add_packed_ref(const char *refname, const unsigned char *sha1)
{
- struct packed_ref_cache *packed_ref_cache =
- get_packed_ref_cache(&ref_store);
+ struct files_ref_store *refs =
+ get_files_ref_store(NULL, "add_packed_ref");
+ struct packed_ref_cache *packed_ref_cache = get_packed_ref_cache(refs);
if (!packed_ref_cache->lock)
die("internal error: packed refs not locked");
@@ -1226,8 +1219,8 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir)
struct strbuf path = STRBUF_INIT;
size_t path_baselen;
- if (*refs->name)
- strbuf_git_path_submodule(&path, refs->name, "%s", dirname);
+ if (*refs->base.submodule)
+ strbuf_git_path_submodule(&path, refs->base.submodule, "%s", dirname);
else
strbuf_git_path(&path, "%s", dirname);
path_baselen = path.len;
@@ -1262,10 +1255,10 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir)
} else {
int read_ok;
- if (*refs->name) {
+ if (*refs->base.submodule) {
hashclr(sha1);
flag = 0;
- read_ok = !resolve_gitlink_ref(refs->name,
+ read_ok = !resolve_gitlink_ref(refs->base.submodule,
refname.buf, sha1);
} else {
read_ok = !read_ref_full(refname.buf,
@@ -1355,8 +1348,8 @@ static int resolve_gitlink_ref_recursive(struct files_ref_store *refs,
if (recursion > SYMREF_MAXDEPTH || strlen(refname) > MAXREFLEN)
return -1;
- path = *refs->name
- ? git_pathdup_submodule(refs->name, "%s", refname)
+ path = *refs->base.submodule
+ ? git_pathdup_submodule(refs->base.submodule, "%s", refname)
: git_pathdup("%s", refname);
fd = open(path, O_RDONLY);
free(path);
@@ -1397,7 +1390,7 @@ int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *sh
return -1;
strbuf_add(&submodule, path, len);
- refs = get_ref_store(submodule.buf);
+ refs = get_files_ref_store(submodule.buf, "resolve_gitlink_ref");
if (!refs) {
strbuf_release(&submodule);
return -1;
@@ -1413,7 +1406,10 @@ int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *sh
*/
static struct ref_entry *get_packed_ref(const char *refname)
{
- return find_ref(get_packed_refs(&ref_store), refname);
+ struct files_ref_store *refs =
+ get_files_ref_store(NULL, "get_packed_ref");
+
+ return find_ref(get_packed_refs(refs), refname);
}
/*
@@ -1613,6 +1609,8 @@ static int lock_raw_ref(const char *refname, int mustexist,
unsigned int *type,
struct strbuf *err)
{
+ struct files_ref_store *refs =
+ get_files_ref_store(NULL, "lock_raw_ref");
struct ref_lock *lock;
struct strbuf ref_file = STRBUF_INIT;
int attempts_remaining = 3;
@@ -1745,7 +1743,7 @@ static int lock_raw_ref(const char *refname, int mustexist,
REMOVE_DIR_EMPTY_ONLY)) {
if (verify_refname_available_dir(
refname, extras, skip,
- get_loose_refs(&ref_store),
+ get_loose_refs(refs),
err)) {
/*
* The error message set by
@@ -1784,7 +1782,7 @@ static int lock_raw_ref(const char *refname, int mustexist,
*/
if (verify_refname_available_dir(
refname, extras, skip,
- get_packed_refs(&ref_store),
+ get_packed_refs(refs),
err)) {
goto error_return;
}
@@ -1942,7 +1940,8 @@ struct ref_iterator *files_ref_iterator_begin(
const char *submodule,
const char *prefix, unsigned int flags)
{
- struct files_ref_store *refs = get_ref_store(submodule);
+ struct files_ref_store *refs =
+ get_files_ref_store(submodule, "ref_iterator_begin");
struct ref_dir *loose_dir, *packed_dir;
struct ref_iterator *loose_iter, *packed_iter;
struct files_ref_iterator *iter;
@@ -2065,6 +2064,8 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
unsigned int flags, int *type,
struct strbuf *err)
{
+ struct files_ref_store *refs =
+ get_files_ref_store(NULL, "lock_ref_sha1_basic");
struct strbuf ref_file = STRBUF_INIT;
struct ref_lock *lock;
int last_errno = 0;
@@ -2095,8 +2096,9 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
*/
if (remove_empty_directories(&ref_file)) {
last_errno = errno;
- if (!verify_refname_available_dir(refname, extras, skip,
- get_loose_refs(&ref_store), err))
+ if (!verify_refname_available_dir(
+ refname, extras, skip,
+ get_loose_refs(refs), err))
strbuf_addf(err, "there are still refs under '%s'",
refname);
goto error_return;
@@ -2107,8 +2109,9 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
if (!resolved) {
last_errno = errno;
if (last_errno != ENOTDIR ||
- !verify_refname_available_dir(refname, extras, skip,
- get_loose_refs(&ref_store), err))
+ !verify_refname_available_dir(
+ refname, extras, skip,
+ get_loose_refs(refs), err))
strbuf_addf(err, "unable to resolve reference '%s': %s",
refname, strerror(last_errno));
@@ -2123,7 +2126,8 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
*/
if (is_null_oid(&lock->old_oid) &&
verify_refname_available_dir(refname, extras, skip,
- get_packed_refs(&ref_store), err)) {
+ get_packed_refs(refs),
+ err)) {
last_errno = ENOTDIR;
goto error_return;
}
@@ -2212,9 +2216,10 @@ static int write_packed_entry_fn(struct ref_entry *entry, void *cb_data)
*/
static int lock_packed_refs(int flags)
{
+ struct files_ref_store *refs =
+ get_files_ref_store(NULL, "lock_packed_refs");
static int timeout_configured = 0;
static int timeout_value = 1000;
-
struct packed_ref_cache *packed_ref_cache;
if (!timeout_configured) {
@@ -2232,7 +2237,7 @@ static int lock_packed_refs(int flags)
* this will automatically invalidate the cache and re-read
* the packed-refs file.
*/
- packed_ref_cache = get_packed_ref_cache(&ref_store);
+ packed_ref_cache = get_packed_ref_cache(refs);
packed_ref_cache->lock = &packlock;
/* Increment the reference count to prevent it from being freed: */
acquire_packed_ref_cache(packed_ref_cache);
@@ -2247,8 +2252,10 @@ static int lock_packed_refs(int flags)
*/
static int commit_packed_refs(void)
{
+ struct files_ref_store *refs =
+ get_files_ref_store(NULL, "commit_packed_refs");
struct packed_ref_cache *packed_ref_cache =
- get_packed_ref_cache(&ref_store);
+ get_packed_ref_cache(refs);
int error = 0;
int save_errno = 0;
FILE *out;
@@ -2281,15 +2288,17 @@ static int commit_packed_refs(void)
*/
static void rollback_packed_refs(void)
{
+ struct files_ref_store *refs =
+ get_files_ref_store(NULL, "rollback_packed_refs");
struct packed_ref_cache *packed_ref_cache =
- get_packed_ref_cache(&ref_store);
+ get_packed_ref_cache(refs);
if (!packed_ref_cache->lock)
die("internal error: packed-refs not locked");
rollback_lock_file(packed_ref_cache->lock);
packed_ref_cache->lock = NULL;
release_packed_ref_cache(packed_ref_cache);
- clear_packed_ref_cache(&ref_store);
+ clear_packed_ref_cache(refs);
}
struct ref_to_prune {
@@ -2422,15 +2431,17 @@ static void prune_refs(struct ref_to_prune *r)
int pack_refs(unsigned int flags)
{
+ struct files_ref_store *refs =
+ get_files_ref_store(NULL, "pack_refs");
struct pack_refs_cb_data cbdata;
memset(&cbdata, 0, sizeof(cbdata));
cbdata.flags = flags;
lock_packed_refs(LOCK_DIE_ON_ERROR);
- cbdata.packed_refs = get_packed_refs(&ref_store);
+ cbdata.packed_refs = get_packed_refs(refs);
- do_for_each_entry_in_dir(get_loose_refs(&ref_store), 0,
+ do_for_each_entry_in_dir(get_loose_refs(refs), 0,
pack_if_possible_fn, &cbdata);
if (commit_packed_refs())
@@ -2449,6 +2460,8 @@ int pack_refs(unsigned int flags)
*/
static int repack_without_refs(struct string_list *refnames, struct strbuf *err)
{
+ struct files_ref_store *refs =
+ get_files_ref_store(NULL, "repack_without_refs");
struct ref_dir *packed;
struct string_list_item *refname;
int ret, needs_repacking = 0, removed = 0;
@@ -2471,7 +2484,7 @@ static int repack_without_refs(struct string_list *refnames, struct strbuf *err)
unable_to_lock_message(git_path("packed-refs"), errno, err);
return -1;
}
- packed = get_packed_refs(&ref_store);
+ packed = get_packed_refs(refs);
/* Remove refnames from the cache */
for_each_string_list_item(refname, refnames)
@@ -2616,8 +2629,10 @@ int verify_refname_available(const char *newname,
const struct string_list *skip,
struct strbuf *err)
{
- struct ref_dir *packed_refs = get_packed_refs(&ref_store);
- struct ref_dir *loose_refs = get_loose_refs(&ref_store);
+ struct files_ref_store *refs =
+ get_files_ref_store(NULL, "verify_refname_available");
+ struct ref_dir *packed_refs = get_packed_refs(refs);
+ struct ref_dir *loose_refs = get_loose_refs(refs);
if (verify_refname_available_dir(newname, extras, skip,
packed_refs, err) ||
@@ -2968,7 +2983,10 @@ static int commit_ref_update(struct ref_lock *lock,
const unsigned char *sha1, const char *logmsg,
struct strbuf *err)
{
- clear_loose_ref_cache(&ref_store);
+ struct files_ref_store *refs =
+ get_files_ref_store(NULL, "commit_ref_update");
+
+ clear_loose_ref_cache(refs);
if (log_ref_write(lock->ref_name, lock->old_oid.hash, sha1, logmsg, 0, err)) {
char *old_msg = strbuf_detach(err, NULL);
strbuf_addf(err, "cannot update the ref '%s': %s",
@@ -3694,6 +3712,8 @@ static int lock_ref_for_update(struct ref_update *update,
int ref_transaction_commit(struct ref_transaction *transaction,
struct strbuf *err)
{
+ struct files_ref_store *refs =
+ get_files_ref_store(NULL, "ref_transaction_commit");
int ret = 0, i;
struct string_list refs_to_delete = STRING_LIST_INIT_NODUP;
struct string_list_item *ref_to_delete;
@@ -3800,7 +3820,7 @@ int ref_transaction_commit(struct ref_transaction *transaction,
}
}
if (update->flags & REF_NEEDS_COMMIT) {
- clear_loose_ref_cache(&ref_store);
+ clear_loose_ref_cache(refs);
if (commit_ref(lock)) {
strbuf_addf(err, "couldn't set '%s'", lock->ref_name);
unlock_ref(lock);
@@ -3833,7 +3853,7 @@ int ref_transaction_commit(struct ref_transaction *transaction,
}
for_each_string_list_item(ref_to_delete, &refs_to_delete)
unlink_or_warn(git_path("logs/%s", ref_to_delete->string));
- clear_loose_ref_cache(&ref_store);
+ clear_loose_ref_cache(refs);
cleanup:
transaction->state = REF_TRANSACTION_CLOSED;
@@ -4079,5 +4099,6 @@ int reflog_expire(const char *refname, const unsigned char *sha1,
struct ref_storage_be refs_be_files = {
NULL,
- "files"
+ "files",
+ files_ref_store_create
};
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index 2c9d134..b952038 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -526,11 +526,89 @@ int read_raw_ref(const char *refname, unsigned char *sha1,
struct strbuf *referent, unsigned int *type);
/* refs backends */
+
+/*
+ * Initialize the ref_store for the specified submodule, or for the
+ * main repository if submodule == NULL. These functions should call
+ * base_ref_store_init() to initialize the shared part of the
+ * ref_store and to record the ref_store for later lookup.
+ */
+typedef struct ref_store *ref_store_init_fn(const char *submodule);
+
struct ref_storage_be {
struct ref_storage_be *next;
const char *name;
+ ref_store_init_fn *init;
};
extern struct ref_storage_be refs_be_files;
+/*
+ * A representation of the reference store for the main repository or
+ * a submodule. The ref_store instances for submodules are kept in a
+ * linked list.
+ */
+struct ref_store {
+ /* The backend describing this ref_store's storage scheme: */
+ const struct ref_storage_be *be;
+
+ /*
+ * The name of the submodule represented by this object, or
+ * the empty string if it represents the main repository's
+ * reference store:
+ */
+ const char *submodule;
+
+ /*
+ * Submodule reference store instances are stored in a linked
+ * list using this pointer.
+ */
+ struct ref_store *next;
+};
+
+/*
+ * Fill in the generic part of refs for the specified submodule and
+ * add it to our collection of reference stores.
+ */
+void base_ref_store_init(struct ref_store *refs,
+ const struct ref_storage_be *be,
+ const char *submodule);
+
+/*
+ * Create, record, and return a ref_store instance for the specified
+ * submodule (or the main repository if submodule is NULL).
+ *
+ * For backwards compatibility, submodule=="" is treated the same as
+ * submodule==NULL.
+ */
+struct ref_store *ref_store_init(const char *submodule);
+
+/*
+ * Return the ref_store instance for the specified submodule (or the
+ * main repository if submodule is NULL). If that ref_store hasn't
+ * been initialized yet, return NULL.
+ *
+ * For backwards compatibility, submodule=="" is treated the same as
+ * submodule==NULL.
+ */
+struct ref_store *lookup_ref_store(const char *submodule);
+
+/*
+ * Return the ref_store instance for the specified submodule. For the
+ * main repository, use submodule==NULL; such a call cannot fail. For
+ * a submodule, the submodule must exist and be a nonbare repository,
+ * otherwise return NULL. If the requested reference store has not yet
+ * been initialized, initialize it first.
+ *
+ * For backwards compatibility, submodule=="" is treated the same as
+ * submodule==NULL.
+ */
+struct ref_store *get_ref_store(const char *submodule);
+
+/*
+ * Die if refs is for a submodule (i.e., not for the main repository).
+ * caller is used in any necessary error messages.
+ */
+void assert_main_repository(struct ref_store *refs, const char *caller);
+
#endif /* REFS_REFS_INTERNAL_H */
--
2.9.3
^ permalink raw reply related
* [PATCH v2 09/38] {lock,commit,rollback}_packed_refs(): add files_ref_store arguments
From: Michael Haggerty @ 2016-09-04 16:08 UTC (permalink / raw)
To: Junio C Hamano
Cc: David Turner, Ramsay Jones, Eric Sunshine, Jeff King,
Nguyễn Thái Ngọc Duy, git, Michael Haggerty
In-Reply-To: <cover.1473003902.git.mhagger@alum.mit.edu>
These functions currently only work in the main repository, so add an
assert_main_repository() check to each function.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs/files-backend.c | 32 ++++++++++++++++----------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 0c92ace..6913d45 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -2215,14 +2215,14 @@ static int write_packed_entry_fn(struct ref_entry *entry, void *cb_data)
* hold_lock_file_for_update(). Return 0 on success. On errors, set
* errno appropriately and return a nonzero value.
*/
-static int lock_packed_refs(int flags)
+static int lock_packed_refs(struct files_ref_store *refs, int flags)
{
- struct files_ref_store *refs =
- get_files_ref_store(NULL, "lock_packed_refs");
static int timeout_configured = 0;
static int timeout_value = 1000;
struct packed_ref_cache *packed_ref_cache;
+ assert_main_repository(&refs->base, "lock_packed_refs");
+
if (!timeout_configured) {
git_config_get_int("core.packedrefstimeout", &timeout_value);
timeout_configured = 1;
@@ -2251,16 +2251,16 @@ static int lock_packed_refs(int flags)
* lock_packed_refs()). Return zero on success. On errors, set errno
* and return a nonzero value
*/
-static int commit_packed_refs(void)
+static int commit_packed_refs(struct files_ref_store *refs)
{
- struct files_ref_store *refs =
- get_files_ref_store(NULL, "commit_packed_refs");
struct packed_ref_cache *packed_ref_cache =
get_packed_ref_cache(refs);
int error = 0;
int save_errno = 0;
FILE *out;
+ assert_main_repository(&refs->base, "commit_packed_refs");
+
if (!packed_ref_cache->lock)
die("internal error: packed-refs not locked");
@@ -2287,13 +2287,13 @@ static int commit_packed_refs(void)
* in-memory packed reference cache. (The packed-refs file will be
* read anew if it is needed again after this function is called.)
*/
-static void rollback_packed_refs(void)
+static void rollback_packed_refs(struct files_ref_store *refs)
{
- struct files_ref_store *refs =
- get_files_ref_store(NULL, "rollback_packed_refs");
struct packed_ref_cache *packed_ref_cache =
get_packed_ref_cache(refs);
+ assert_main_repository(&refs->base, "rollback_packed_refs");
+
if (!packed_ref_cache->lock)
die("internal error: packed-refs not locked");
rollback_lock_file(packed_ref_cache->lock);
@@ -2439,13 +2439,13 @@ int pack_refs(unsigned int flags)
memset(&cbdata, 0, sizeof(cbdata));
cbdata.flags = flags;
- lock_packed_refs(LOCK_DIE_ON_ERROR);
+ lock_packed_refs(refs, LOCK_DIE_ON_ERROR);
cbdata.packed_refs = get_packed_refs(refs);
do_for_each_entry_in_dir(get_loose_refs(refs), 0,
pack_if_possible_fn, &cbdata);
- if (commit_packed_refs())
+ if (commit_packed_refs(refs))
die_errno("unable to overwrite old ref-pack file");
prune_refs(cbdata.ref_to_prune);
@@ -2481,7 +2481,7 @@ static int repack_without_refs(struct string_list *refnames, struct strbuf *err)
if (!needs_repacking)
return 0; /* no refname exists in packed refs */
- if (lock_packed_refs(0)) {
+ if (lock_packed_refs(refs, 0)) {
unable_to_lock_message(git_path("packed-refs"), errno, err);
return -1;
}
@@ -2496,12 +2496,12 @@ static int repack_without_refs(struct string_list *refnames, struct strbuf *err)
* All packed entries disappeared while we were
* acquiring the lock.
*/
- rollback_packed_refs();
+ rollback_packed_refs(refs);
return 0;
}
/* Write what remains */
- ret = commit_packed_refs();
+ ret = commit_packed_refs(refs);
if (ret)
strbuf_addf(err, "unable to overwrite old ref-pack file: %s",
strerror(errno));
@@ -3929,7 +3929,7 @@ int initial_ref_transaction_commit(struct ref_transaction *transaction,
}
}
- if (lock_packed_refs(0)) {
+ if (lock_packed_refs(refs, 0)) {
strbuf_addf(err, "unable to lock packed-refs file: %s",
strerror(errno));
ret = TRANSACTION_GENERIC_ERROR;
@@ -3944,7 +3944,7 @@ int initial_ref_transaction_commit(struct ref_transaction *transaction,
add_packed_ref(refs, update->refname, update->new_sha1);
}
- if (commit_packed_refs()) {
+ if (commit_packed_refs(refs)) {
strbuf_addf(err, "unable to commit packed-refs file: %s",
strerror(errno));
ret = TRANSACTION_GENERIC_ERROR;
--
2.9.3
^ permalink raw reply related
* [PATCH v2 21/38] refs: make pack_refs() virtual
From: Michael Haggerty @ 2016-09-04 16:08 UTC (permalink / raw)
To: Junio C Hamano
Cc: David Turner, Ramsay Jones, Eric Sunshine, Jeff King,
Nguyễn Thái Ngọc Duy, git, Michael Haggerty
In-Reply-To: <cover.1473003902.git.mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs.c | 7 +++++++
refs/files-backend.c | 6 ++++--
refs/refs-internal.h | 4 ++++
3 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/refs.c b/refs.c
index 662c417..961927a 100644
--- a/refs.c
+++ b/refs.c
@@ -1421,6 +1421,13 @@ void assert_main_repository(struct ref_store *refs, const char *caller)
}
/* backend functions */
+int pack_refs(unsigned int flags)
+{
+ struct ref_store *refs = get_ref_store(NULL);
+
+ return refs->be->pack_refs(refs, flags);
+}
+
int ref_transaction_commit(struct ref_transaction *transaction,
struct strbuf *err)
{
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 4e1d431..7ad8821 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -2354,10 +2354,10 @@ static void prune_refs(struct ref_to_prune *r)
}
}
-int pack_refs(unsigned int flags)
+static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)
{
struct files_ref_store *refs =
- get_files_ref_store(NULL, "pack_refs");
+ files_downcast(ref_store, 0, "pack_refs");
struct pack_refs_cb_data cbdata;
memset(&cbdata, 0, sizeof(cbdata));
@@ -4032,6 +4032,8 @@ struct ref_storage_be refs_be_files = {
files_ref_store_create,
files_transaction_commit,
+ files_pack_refs,
+
files_read_raw_ref,
files_verify_refname_available
};
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index 6c698f4..256f7f5 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -500,6 +500,8 @@ typedef int ref_transaction_commit_fn(struct ref_store *refs,
struct ref_transaction *transaction,
struct strbuf *err);
+typedef int pack_refs_fn(struct ref_store *ref_store, unsigned int flags);
+
/*
* Read a reference from the specified reference store, non-recursively.
* Set type to describe the reference, and:
@@ -554,6 +556,8 @@ struct ref_storage_be {
ref_store_init_fn *init;
ref_transaction_commit_fn *transaction_commit;
+ pack_refs_fn *pack_refs;
+
read_raw_ref_fn *read_raw_ref;
verify_refname_available_fn *verify_refname_available;
};
--
2.9.3
^ permalink raw reply related
* [PATCH v2 23/38] refs: make peel_ref() virtual
From: Michael Haggerty @ 2016-09-04 16:08 UTC (permalink / raw)
To: Junio C Hamano
Cc: David Turner, Ramsay Jones, Eric Sunshine, Jeff King,
Nguyễn Thái Ngọc Duy, git, Michael Haggerty
In-Reply-To: <cover.1473003902.git.mhagger@alum.mit.edu>
For now it only supports the main reference store.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
refs.c | 7 +++++++
refs/files-backend.c | 6 ++++--
refs/refs-internal.h | 3 +++
3 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/refs.c b/refs.c
index 74874e5..f10f86a 100644
--- a/refs.c
+++ b/refs.c
@@ -1428,6 +1428,13 @@ int pack_refs(unsigned int flags)
return refs->be->pack_refs(refs, flags);
}
+int peel_ref(const char *refname, unsigned char *sha1)
+{
+ struct ref_store *refs = get_ref_store(NULL);
+
+ return refs->be->peel_ref(refs, refname, sha1);
+}
+
int create_symref(const char *ref_target, const char *refs_heads_master,
const char *logmsg)
{
diff --git a/refs/files-backend.c b/refs/files-backend.c
index bf53670..8d43e0b 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1759,9 +1759,10 @@ static enum peel_status peel_entry(struct ref_entry *entry, int repeel)
return status;
}
-int peel_ref(const char *refname, unsigned char *sha1)
+static int files_peel_ref(struct ref_store *ref_store,
+ const char *refname, unsigned char *sha1)
{
- struct files_ref_store *refs = get_files_ref_store(NULL, "peel_ref");
+ struct files_ref_store *refs = files_downcast(ref_store, 0, "peel_ref");
int flag;
unsigned char base[20];
@@ -4037,6 +4038,7 @@ struct ref_storage_be refs_be_files = {
files_transaction_commit,
files_pack_refs,
+ files_peel_ref,
files_create_symref,
files_read_raw_ref,
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index bf96503..84c81ad 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -501,6 +501,8 @@ typedef int ref_transaction_commit_fn(struct ref_store *refs,
struct strbuf *err);
typedef int pack_refs_fn(struct ref_store *ref_store, unsigned int flags);
+typedef int peel_ref_fn(struct ref_store *ref_store,
+ const char *refname, unsigned char *sha1);
typedef int create_symref_fn(struct ref_store *ref_store,
const char *ref_target,
const char *refs_heads_master,
@@ -561,6 +563,7 @@ struct ref_storage_be {
ref_transaction_commit_fn *transaction_commit;
pack_refs_fn *pack_refs;
+ peel_ref_fn *peel_ref;
create_symref_fn *create_symref;
read_raw_ref_fn *read_raw_ref;
--
2.9.3
^ permalink raw reply related
* Re: [PATCH v13 10/14] apply: change error_routine when silent
From: Ramsay Jones @ 2016-09-04 16:31 UTC (permalink / raw)
To: Christian Couder, Stefan Beller
Cc: git@vger.kernel.org, Junio C Hamano, Jeff King,
Ævar Arnfjörð Bjarmason, Karsten Blees,
Nguyen Thai Ngoc Duy, Eric Sunshine, Johannes Sixt,
René Scharfe, Stefan Naewe, Christian Couder
In-Reply-To: <CAP8UFD38CC-Ah9zVcnU3a4nGH2CzOn74Adx=42pmckjPv=e_Bg@mail.gmail.com>
On 04/09/16 11:54, Christian Couder wrote:
> On Thu, Sep 1, 2016 at 10:19 AM, Christian Couder
> <christian.couder@gmail.com> wrote:
>> On Thu, Sep 1, 2016 at 12:20 AM, Stefan Beller <sbeller@google.com> wrote:
>>> On Sat, Aug 27, 2016 at 11:45 AM, Christian Couder
>>> <christian.couder@gmail.com> wrote:
>>>> To avoid printing anything when applying with
>>>> `state->apply_verbosity == verbosity_silent`, let's save the
>>>> existing warn and error routines before applying, and let's
>>>> replace them with a routine that does nothing.
>>>>
>>>> Then after applying, let's restore the saved routines.
>>>>
>>>> Helped-by: Stefan Beller <sbeller@google.com>
>>>> Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
>>>> ---
>>>> apply.c | 21 ++++++++++++++++++++-
>>>> apply.h | 8 ++++++++
>>>> 2 files changed, 28 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/apply.c b/apply.c
>>>> index ddbb0a2..bf81b70 100644
>>>> --- a/apply.c
>>>> +++ b/apply.c
>>>> @@ -112,6 +112,11 @@ void clear_apply_state(struct apply_state *state)
>>>> /* &state->fn_table is cleared at the end of apply_patch() */
>>>> }
>>>>
>>>> +static void mute_routine(const char *bla, va_list params)
>>>
>>> Instead of 'bla' you could go with 'format' as the man page for
>>> [f]printf puts it.
>>> Or you could leave it empty, i.e.
>>>
>>> static void mute_routine(const char *, va_list)
>>> ...
>>
>> Ok to do that.
>
> Actually I get the following error when doing that:
>
> apply.c: In function ‘mute_routine’:
> apply.c:115:1: error: parameter name omitted
> static void mute_routine(const char *, va_list)
> ^
> apply.c:115:1: error: parameter name omitted
> make: *** [apply.o] Error 1
Yes, this is not C++. ;-)
> So I will leave it as is.
I think I would prefer to see:
static void mute_routine(const char *msg, va_list params)
given that it would either be an error-msg or a warning-msg.
ATB,
Ramsay Jones
^ permalink raw reply
* Re: [PATCH v13 10/14] apply: change error_routine when silent
From: Christian Couder @ 2016-09-04 16:45 UTC (permalink / raw)
To: Ramsay Jones
Cc: Stefan Beller, git@vger.kernel.org, Junio C Hamano, Jeff King,
Ævar Arnfjörð Bjarmason, Karsten Blees,
Nguyen Thai Ngoc Duy, Eric Sunshine, Johannes Sixt,
René Scharfe, Stefan Naewe, Christian Couder
In-Reply-To: <e39d9b83-949b-075c-07f6-60118dc24961@ramsayjones.plus.com>
On Sun, Sep 4, 2016 at 6:31 PM, Ramsay Jones
<ramsay@ramsayjones.plus.com> wrote:
>
>
> On 04/09/16 11:54, Christian Couder wrote:
>> On Thu, Sep 1, 2016 at 10:19 AM, Christian Couder
>> <christian.couder@gmail.com> wrote:
>>> On Thu, Sep 1, 2016 at 12:20 AM, Stefan Beller <sbeller@google.com> wrote:
>>>>>
>>>>> +static void mute_routine(const char *bla, va_list params)
>>>>
>>>> Instead of 'bla' you could go with 'format' as the man page for
>>>> [f]printf puts it.
>>>> Or you could leave it empty, i.e.
>>>>
>>>> static void mute_routine(const char *, va_list)
>>>> ...
>>>
>>> Ok to do that.
>>
>> Actually I get the following error when doing that:
>>
>> apply.c: In function ‘mute_routine’:
>> apply.c:115:1: error: parameter name omitted
>> static void mute_routine(const char *, va_list)
>> ^
>> apply.c:115:1: error: parameter name omitted
>> make: *** [apply.o] Error 1
>
> Yes, this is not C++. ;-)
>
>> So I will leave it as is.
>
> I think I would prefer to see:
>
> static void mute_routine(const char *msg, va_list params)
>
> given that it would either be an error-msg or a warning-msg.
Ok for "msg".
^ permalink raw reply
* [WIP PATCH v2] diff.c: emit moved lines with a different color
From: Stefan Beller @ 2016-09-04 19:14 UTC (permalink / raw)
To: git; +Cc: jnareb, gitster, jacob.keller, Stefan Beller
From: Stefan Beller <sbeller@google.com>
When we color the diff, we'll mark moved lines with a different color.
This is achieved by doing a two passes over the diff. The first pass
will inspect each line of the diff and store the removed lines and the
added lines in its own hash map.
The second pass will check for each added line if that is found in the
set of removed lines. If so it will color the added line differently as
with the new `moved-new` color mode.
For each removed line we check the set of added lines and if found emit
that with the new color `moved-old`.
When detecting the moved lines, we cannot just rely on a line being equal,
but we need to take the context into account to detect when the moves were
reordered as we do not want to color moved but per-mutated lines.
This patch was motivated by e.g. reviewing 3b0c4200 ("apply: move
libified code from builtin/apply.c to apply.{c,h}", 2016-08-08)
Signed-off-by: Stefan Beller <sbeller@google.com>
---
This adds code only in the diff_flush part, just as you suggested Junio.
I think the design is sound now, as it produces good highlights across files;
though now the code still sucks.
* leaking memory;
* we run the code to detect moves more often than we need, e.g.
when we configured an external diff, we don't need to run it.
Or when we do not use colors at all.
* I need to think about if we need everything doubled for both add and
removal; maybe we can use one variable for both cases.
Jacob wrote:
> In the example, the first and last lines of duplicate copies don't get
> colored differently, and that threw me off. I feel like that was
> maybe not intentional? If it was, can you explain why?
We need the context to detect permutations, improved version:
http://i.imgur.com/MnaSZ1D.png
Jakub wrote:
> P.S. BTW. does this work with word-diff?
No (not yet.... )
Thanks,
Stefan
Documentation/config.txt | 5 +-
contrib/completion/git-completion.bash | 2 +
diff.c | 200 ++++++++++++++++++++++++++++++++-
diff.h | 5 +-
4 files changed, 205 insertions(+), 7 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 0bcb679..f4f51c2 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -980,8 +980,9 @@ color.diff.<slot>::
of `context` (context text - `plain` is a historical synonym),
`meta` (metainformation), `frag`
(hunk header), 'func' (function in hunk header), `old` (removed lines),
- `new` (added lines), `commit` (commit headers), or `whitespace`
- (highlighting whitespace errors).
+ `new` (added lines), `commit` (commit headers), `whitespace`
+ (highlighting whitespace errors), `moved-old` (removed lines that
+ reappear), `moved-new` (added lines that were removed elsewhere).
color.decorate.<slot>::
Use customized color for 'git log --decorate' output. `<slot>` is one
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 9c8f738..b558d12 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -2115,6 +2115,8 @@ _git_config ()
color.diff.old
color.diff.plain
color.diff.whitespace
+ color.diff.moved-old
+ color.diff.moved-new
color.grep
color.grep.context
color.grep.filename
diff --git a/diff.c b/diff.c
index 534c12e..d37cb4f 100644
--- a/diff.c
+++ b/diff.c
@@ -18,6 +18,7 @@
#include "ll-merge.h"
#include "string-list.h"
#include "argv-array.h"
+#include "git-compat-util.h"
#ifdef NO_FAST_WORKING_DIRECTORY
#define FAST_WORKING_DIRECTORY 0
@@ -42,6 +43,11 @@ static int diff_dirstat_permille_default = 30;
static struct diff_options default_diff_options;
static long diff_algorithm;
+static struct hashmap *duplicates_added;
+static struct hashmap *duplicates_removed;
+static int hash_previous_line_added;
+static int hash_previous_line_removed;
+
static char diff_colors[][COLOR_MAXLEN] = {
GIT_COLOR_RESET,
GIT_COLOR_NORMAL, /* CONTEXT */
@@ -52,6 +58,8 @@ static char diff_colors[][COLOR_MAXLEN] = {
GIT_COLOR_YELLOW, /* COMMIT */
GIT_COLOR_BG_RED, /* WHITESPACE */
GIT_COLOR_NORMAL, /* FUNCINFO */
+ GIT_COLOR_BLUE, /* NEW MOVED */
+ GIT_COLOR_MAGENTA, /* OLD MOVED */
};
static int parse_diff_color_slot(const char *var)
@@ -72,6 +80,10 @@ static int parse_diff_color_slot(const char *var)
return DIFF_WHITESPACE;
if (!strcasecmp(var, "func"))
return DIFF_FUNCINFO;
+ if (!strcasecmp(var, "moved-old"))
+ return DIFF_FILE_MOVED_OLD;
+ if (!strcasecmp(var, "moved-new"))
+ return DIFF_FILE_MOVED_NEW;
return -1;
}
@@ -287,6 +299,30 @@ int git_diff_basic_config(const char *var, const char *value, void *cb)
return git_default_config(var, value, cb);
}
+struct dup_entry {
+ struct hashmap_entry ent;
+ char *line;
+ int previous_hash;
+};
+
+static int dup_entry_cmp(const struct dup_entry *a,
+ const struct dup_entry *b,
+ const void *unused)
+{
+ return strcmp(a->line, b->line) && a->previous_hash == b->previous_hash;
+}
+
+static struct dup_entry *prepare_entry(const char *line,
+ unsigned long len,
+ int previous_hash)
+{
+ struct dup_entry *ret = xmalloc(sizeof(*ret));
+ ret->ent.hash = memhash(line, len) ^ previous_hash;
+ ret->line = xmemdupz(line, len);
+ ret->previous_hash = previous_hash;
+ return ret;
+}
+
static char *quote_two(const char *one, const char *two)
{
int need_one = quote_c_style(one, NULL, NULL, 1);
@@ -537,16 +573,46 @@ static void emit_add_line(const char *reset,
struct emit_callback *ecbdata,
const char *line, int len)
{
- emit_line_checked(reset, ecbdata, line, len,
- DIFF_FILE_NEW, WSEH_NEW, '+');
+ if (!duplicates_removed) {
+ emit_line_checked(reset, ecbdata, line, len,
+ DIFF_FILE_NEW, WSEH_NEW, '+');
+ } else {
+ int hash = memhash(line, len);
+ struct dup_entry *keydata = prepare_entry(line, len, hash_previous_line_added);
+ enum color_diff color = DIFF_FILE_NEW;
+ unsigned ws_error_highlight = WSEH_NEW;
+
+ if (hashmap_get(duplicates_removed, keydata, keydata))
+ color = DIFF_FILE_MOVED_NEW;
+
+ emit_line_checked(reset, ecbdata, line, len,
+ color, ws_error_highlight, '+');
+
+ hash_previous_line_added = hash;
+ }
}
static void emit_del_line(const char *reset,
struct emit_callback *ecbdata,
const char *line, int len)
{
- emit_line_checked(reset, ecbdata, line, len,
- DIFF_FILE_OLD, WSEH_OLD, '-');
+ if (!duplicates_added) {
+ emit_line_checked(reset, ecbdata, line, len,
+ DIFF_FILE_OLD, WSEH_OLD, '-');
+ } else {
+ int hash = memhash(line, len);
+ struct dup_entry *keydata = prepare_entry(line, len, hash_previous_line_removed);
+ enum color_diff color = DIFF_FILE_OLD;
+ unsigned ws_error_highlight = WSEH_OLD;
+
+ if (hashmap_get(duplicates_added, keydata, keydata))
+ color = DIFF_FILE_MOVED_OLD;
+
+ emit_line_checked(reset, ecbdata, line, len,
+ color, ws_error_highlight, '-');
+
+ hash_previous_line_removed = hash;
+ }
}
static void emit_context_line(const char *reset,
@@ -555,6 +621,11 @@ static void emit_context_line(const char *reset,
{
emit_line_checked(reset, ecbdata, line, len,
DIFF_CONTEXT, WSEH_CONTEXT, ' ');
+ if (duplicates_added) {
+ int hash = memhash(line, len);
+ hash_previous_line_removed = hash;
+ hash_previous_line_added = hash;
+ }
}
static void emit_hunk_header(struct emit_callback *ecbdata,
@@ -1323,6 +1394,59 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
}
}
+static void fn_prepare_consume(void *priv, char *line, unsigned long len)
+{
+ int hash;
+ struct dup_entry *d;
+
+ if (!duplicates_added) {
+ duplicates_added = xmalloc(sizeof(*duplicates_added));
+ duplicates_removed = xmalloc(sizeof(*duplicates_removed));
+ hashmap_init(duplicates_added, (hashmap_cmp_fn)dup_entry_cmp, 0);
+ hashmap_init(duplicates_removed, (hashmap_cmp_fn)dup_entry_cmp, 0);
+ }
+
+ switch (line[0]) {
+ case ' ':
+ d = prepare_entry(line + 1, len - 1, 0);
+ hashmap_add(duplicates_removed, d);
+ hashmap_add(duplicates_added, d);
+ break;
+ case '+':
+ if (hash_previous_line_added)
+ hashmap_add(duplicates_added,
+ prepare_entry(line + 1, len - 1,
+ hash_previous_line_added));
+ break;
+ case '-':
+ if (hash_previous_line_removed)
+ hashmap_add(duplicates_removed,
+ prepare_entry(line + 1, len - 1,
+ hash_previous_line_removed));
+ break;
+ }
+
+ hash = memhash(line + 1, len - 1);
+ switch (line[0]) {
+ case ' ':
+ hash_previous_line_added = hash;
+ hash_previous_line_removed = hash;
+ break;
+ case '+':
+ hash_previous_line_added = hash;
+ hash_previous_line_removed = 0;
+ break;
+ case '-':
+ hash_previous_line_added = 0;
+ hash_previous_line_removed = hash;
+ break;
+ default:
+ hash_previous_line_added = 0;
+ hash_previous_line_removed = 0;
+ break;
+ }
+}
+
static char *pprint_rename(const char *a, const char *b)
{
const char *old = a;
@@ -2279,6 +2403,50 @@ struct userdiff_driver *get_textconv(struct diff_filespec *one)
return userdiff_get_textconv(one->driver);
}
+
+static void prepare_moved_lines(struct diff_filepair *p, struct diff_options *o)
+{
+ struct diff_filespec *one = p->one;
+ struct diff_filespec *two = p->two;
+ struct userdiff_driver *textconv_one = NULL;
+ struct userdiff_driver *textconv_two = NULL;
+
+ if (DIFF_OPT_TST(o, ALLOW_TEXTCONV)) {
+ textconv_one = get_textconv(one);
+ textconv_two = get_textconv(two);
+ }
+
+ {
+ mmfile_t mf1, mf2;
+ xpparam_t xpp;
+ xdemitconf_t xecfg;
+ struct emit_callback ecbdata;
+
+ mf1.size = fill_textconv(textconv_one, one, &mf1.ptr);
+ mf2.size = fill_textconv(textconv_two, two, &mf2.ptr);
+
+ memset(&xpp, 0, sizeof(xpp));
+ memset(&xecfg, 0, sizeof(xecfg));
+ memset(&ecbdata, 0, sizeof(ecbdata));
+
+ xpp.flags = o->xdl_opts;
+ xecfg.ctxlen = 1;
+
+ if (o->word_diff)
+ init_diff_words_data(&ecbdata, o, one, two);
+ if (xdi_diff_outf(&mf1, &mf2, fn_prepare_consume, &ecbdata,
+ &xpp, &xecfg))
+ die("unable to generate diff for %s", one->path);
+ if (o->word_diff)
+ free_diff_words_data(&ecbdata);
+ if (textconv_one)
+ free(mf1.ptr);
+ if (textconv_two)
+ free(mf2.ptr);
+ xdiff_clear_find_func(&xecfg);
+ }
+}
+
static void builtin_diff(const char *name_a,
const char *name_b,
struct diff_filespec *one,
@@ -3295,6 +3463,7 @@ void diff_setup(struct diff_options *options)
options->xdl_opts |= diff_algorithm;
if (diff_compaction_heuristic)
DIFF_XDL_SET(options, COMPACTION_HEURISTIC);
+ options->highlight_moved = options->use_color;
options->orderfile = diff_order_file_cfg;
@@ -3413,6 +3582,9 @@ void diff_setup_done(struct diff_options *options)
if (DIFF_OPT_TST(options, FOLLOW_RENAMES) && options->pathspec.nr != 1)
die(_("--follow requires exactly one pathspec"));
+
+ if (!options->use_color)
+ options->highlight_moved = 0;
}
static int opt_arg(const char *arg, int arg_short, const char *arg_long, int *val)
@@ -4622,6 +4794,24 @@ void diff_warn_rename_limit(const char *varname, int needed, int degraded_cc)
warning(rename_limit_advice, varname, needed);
}
+static void diff_flush_maybe_prepare_moved_lines(struct diff_options *o)
+{
+ int i;
+ struct diff_queue_struct *q = &diff_queued_diff;
+ if (0
+ /* TODO
+ * internal diff and colored options, i.e.
+ * only when we actually run into the emit_line_...
+ * eventually */)
+ return;
+
+ for (i = 0; i < q->nr; i++) {
+ struct diff_filepair *p = q->queue[i];
+ if (check_pair_status(p))
+ prepare_moved_lines(p, o);
+ }
+}
+
void diff_flush(struct diff_options *options)
{
struct diff_queue_struct *q = &diff_queued_diff;
@@ -4716,6 +4906,8 @@ void diff_flush(struct diff_options *options)
}
}
+
+ diff_flush_maybe_prepare_moved_lines(options);
for (i = 0; i < q->nr; i++) {
struct diff_filepair *p = q->queue[i];
if (check_pair_status(p))
diff --git a/diff.h b/diff.h
index 7883729..0e4367b 100644
--- a/diff.h
+++ b/diff.h
@@ -139,6 +139,7 @@ struct diff_options {
int dirstat_permille;
int setup;
int abbrev;
+ int highlight_moved;
/* white-space error highlighting */
#define WSEH_NEW 1
#define WSEH_CONTEXT 2
@@ -189,7 +190,9 @@ enum color_diff {
DIFF_FILE_NEW = 5,
DIFF_COMMIT = 6,
DIFF_WHITESPACE = 7,
- DIFF_FUNCINFO = 8
+ DIFF_FUNCINFO = 8,
+ DIFF_FILE_MOVED_NEW = 9,
+ DIFF_FILE_MOVED_OLD = 10
};
const char *diff_get_color(int diff_use_color, enum color_diff ix);
#define diff_get_color_opt(o, ix) \
--
2.10.0.2.ga528ff4
^ permalink raw reply related
* Re: [PATCH v2 04/38] refs: add a backend method structure
From: David Turner @ 2016-09-04 19:43 UTC (permalink / raw)
To: Michael Haggerty
Cc: Junio C Hamano, Ramsay Jones, Eric Sunshine, Jeff King,
Nguyễn Thái Ngọc Duy, git, Ronnie Sahlberg,
David Turner
In-Reply-To: <4da46c8dfa4b7ec13927ca8597b64ffff7de4430.1473003902.git.mhagger@alum.mit.edu>
On Sun, 2016-09-04 at 18:08 +0200, Michael Haggerty wrote:
> From: Ronnie Sahlberg <sahlberg@google.com>
>
> Add a `struct ref_storage_be` to represent types of reference stores. In
> OO notation, this is the class, and will soon hold some class
> methods (e.g., a factory to create new ref_store instances) and will
> also serve as the vtable for ref_store instances of that type.
>
> As yet, the backends cannot do anything.
>
> Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
> Signed-off-by: David Turner <dturner@twopensource.com>
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
> Signed-off-by: Jeff King <peff@peff.net>
> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
nit: duplicate Sign-off from Junio.
^ permalink raw reply
* Re: [PATCH v13 00/14] libify apply and use lib in am, part 3
From: Christian Couder @ 2016-09-04 20:17 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Ævar Arnfjörð Bjarmason,
Karsten Blees, Nguyen Thai Ngoc Duy, Stefan Beller, Eric Sunshine,
Ramsay Jones, Johannes Sixt, René Scharfe, Stefan Naewe,
Christian Couder
In-Reply-To: <xmqqzinrwly4.fsf@gitster.mtv.corp.google.com>
On Thu, Sep 1, 2016 at 7:48 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Christian Couder <christian.couder@gmail.com> writes:
>
>> Following Stefan's review, it looks like I will need to resend at
>> least 02/14, 10/14 and 14/14.
>> What do you prefer me to resend:
>> 1) all the last 40 or so patches
>> 2) the last 14 patches
>> 3) only the few patches that changed
>
> If this reroll is to be the candidate to be the final one, I'd
> prefer to see 1 to give an easy access to more sets of eyes, but if
> you just send them without giving these patches one more read-over
> before sending them out, it is not as valuable as it would be.
Ok, I will send the 41 patches very soon after having given them one
more read over and implementing the few changes suggested by Stefan
and Ramsay and one improvement I spotted.
> I think 2 is of the least value.
>
> If you do 3., pointing people at where the remainder of the series
> can be found is necessary.
There is always a pointer to the full patch series on GitHub anyway in
the cover letter, but I will send everything anyway.
^ permalink raw reply
* [PATCH v14 00/41] libify apply and use lib in am, part 2
From: Christian Couder @ 2016-09-04 20:17 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Ævar Arnfjörð Bjarmason,
Karsten Blees, Nguyen Thai Ngoc Duy, Stefan Beller, Eric Sunshine,
Ramsay Jones, Johannes Sixt, René Scharfe, Stefan Naewe,
Christian Couder
Goal
~~~~
This is a patch series about libifying `git apply` functionality, and
using this libified functionality in `git am`, so that no 'git apply'
process is spawn anymore. This makes `git am` significantly faster, so
`git rebase`, when it uses the am backend, is also significantly
faster.
Previous discussions and patches series
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This has initially been discussed in the following thread:
http://thread.gmane.org/gmane.comp.version-control.git/287236/
Then the following patch series were sent:
RFC: http://thread.gmane.org/gmane.comp.version-control.git/288489/
v1: http://thread.gmane.org/gmane.comp.version-control.git/292324/
v2: http://thread.gmane.org/gmane.comp.version-control.git/294248/
v3: http://thread.gmane.org/gmane.comp.version-control.git/295429/
v4: http://thread.gmane.org/gmane.comp.version-control.git/296350/
v5: http://thread.gmane.org/gmane.comp.version-control.git/296490/
v6: http://thread.gmane.org/gmane.comp.version-control.git/297024/
v7: http://thread.gmane.org/gmane.comp.version-control.git/297193/
v8: https://public-inbox.org/git/20160627182429.31550-1-chriscool%40tuxfamily.org/
v9: https://public-inbox.org/git/20160730172509.22939-1-chriscool%40tuxfamily.org/
v10: https://public-inbox.org/git/20160808210337.5038-1-chriscool%40tuxfamily.org/
v11: https://public-inbox.org/git/20160811085229.19017-1-chriscool%40tuxfamily.org/
v12: https://public-inbox.org/git/20160811184501.384-1-chriscool@tuxfamily.org/
v13: https://public-inbox.org/git/20160827184547.4365-1-chriscool@tuxfamily.org/
Highlevel view of the patches in the series
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This is "part 2" of the full patch series. I am resending everything
that is not already in master to give people another chance to review
everything.
- Patch 01/41 to 27/41 were in v10, but not in v11, v12, and v13.
They libify the apply functions by making them return error codes
instead of die()ing or exit()ing and by making sure they release all
the resources they use.
There is only one change in patch 26/41 where I now use error_errno()
right away instead of first using error() and then converting the
error() into error_errno() in patch 32/41.
- Patches 28/41 to 31/41 were in v12 and v13.
They finish libifying the apply functionality that was in
builtin/apply.c and move it into apply.{c,h}, but the libified
functionality is not yet used in `git am`.
In patch 29/41 I added some comments in apply.h above the definition
of APPLY_OPT_INACCURATE_EOF and APPLY_OPT_RECOUNT, as suggested by
Stefan. This is the only change compared to v13.
- Patch 32/41 was in v10, v12 and v13.
It replaces some calls to error() with calls to error_errno().
One hunk has been removed because of the changes in 26/41.
- Patches 33/41 to 37/41 were in v10, v12 and v13.
They implement a way to make the libified apply code silent by
changing the bool `apply_verbosely` into a tristate enum called
`apply_verbosity`, that can be one of `verbosity_verbose`,
`verbosity_normal` or `verbosity_silent`.
The only changes since v13 are in 37/41. The name of the first
argument to mute_routine() is changed from "bla" to "msg" as suggested
by Ramsey, and the commit message is improved as suggested by Stefan.
- Patch 38/41 was in v10, v12 and v13, and hasn't changed.
It refactors `git apply` option parsing to make it possible for `git
am` to easily pass some command line options to the libified applied
code.
- Patch 39/41 was new in v13, and hasn't changed.
It is a refactoring to prepare for patch 40/41.
- Patch 40/41 was in v12 and v13, and hasn't changed.
It adds a "const char *index_file" into "struct apply_state", to make
it possible to use a special index file instead of the default one.
- Patch 41/41 was in v10, v12 and v13.
This patch makes `git am` use the libified functionality.
The only change compared to v13 is that "through" instead of "thru" is
used in an error message.
General comments
~~~~~~~~~~~~~~~~
Now this patch series is 41 patches long to give yet another
possibility for all the patches to be reviewed.
I took another look at all these patches myself and didn't find
anything other than the changes I made in 26/41 to improve.
I will send a diff between this version and v13 as a reply to this
email.
The benefits are not just related to not creating new processes. When
`git am` launched a `git apply` process, this new process had to read
the index from disk. Then after the `git apply`process had terminated,
`git am` dropped its index and read the index from disk to get the
index that had been modified by the `git apply`process. This was
inefficient and also prevented the split-index mechanism to provide
many performance benefits.
By the way, current work is ongoing to make it possible to use
split-index more easily by adding a config variable, see:
https://public-inbox.org/git/20160711172254.13439-1-chriscool%40tuxfamily.org/
Using an earlier version of this series as rebase material, Duy
explained split-index benefits along with this patch series like this:
> Without the series, the picture is not so surprising. We run git-apply
> 80+ times, each consists of this sequence
>
> read index
> write index (cache tree updates only)
> read index again
> optionally initialize name hash (when new entries are added, I guess)
> read packed-refs
> write index
>
> With this series, we run a single git-apply which does
>
> read index (and sharedindex too if in split-index mode)
> initialize name hash
> write index 80+ times
(See: http://thread.gmane.org/gmane.comp.version-control.git/292324/focus=292460)
Links
~~~~~
This patch series is available here:
https://github.com/chriscool/git/commits/libify-apply-use-in-am
The previous versions are available there:
v1: https://github.com/chriscool/git/commits/libify-apply-use-in-am25
v2: https://github.com/chriscool/git/commits/libify-apply-use-in-am54
v6: https://github.com/chriscool/git/commits/libify-apply-use-in-am65
v7: https://github.com/chriscool/git/commits/libify-apply-use-in-am75
v8: https://github.com/chriscool/git/commits/libify-apply-use-in-am97
v9: https://github.com/chriscool/git/commits/libify-apply-use-in-am106
v10: https://github.com/chriscool/git/commits/libify-apply-use-in-am114
v11: https://github.com/chriscool/git/commits/libify-apply-use-in-am116
v12: https://github.com/chriscool/git/commits/libify-apply-use-in-am118
v13: https://github.com/chriscool/git/commits/libify-apply-use-in-am120
Performance numbers
~~~~~~~~~~~~~~~~~~~
Numbers are only available for tests that have been performed on Linux
using a very early version of this series, though Johannes Sixt
reported great improvements on Windows. It could be interesting to get
detailed numbers on other platforms like Windows and OSX.
- Around mid April Ævar did a huge many-hundred commit rebase on the
kernel with untracked cache.
command: git rebase --onto 1993b17 52bef0c 29dde7c
Vanilla "next" without split index: 1m54.953s
Vanilla "next" with split index: 1m22.476s
This series on top of "next" without split index: 1m12.034s
This series on top of "next" with split index: 0m15.678s
Ævar used his Debian laptop with SSD.
- Around mid April I tested rebasing 13 commits in Booking.com's
monorepo on a Red Hat 6.5 server with split-index and
GIT_TRACE_PERFORMANCE=1.
With Git v2.8.0, the rebase took 6.375888383 s, with the git am
command launched by the rebase command taking 3.705677431 s.
With this series on top of next, the rebase took 3.044529494 s, with
the git am command launched by the rebase command taking 0.583521168
s.
Christian Couder (41):
apply: make some names more specific
apply: move 'struct apply_state' to apply.h
builtin/apply: make apply_patch() return -1 or -128 instead of
die()ing
builtin/apply: read_patch_file() return -1 instead of die()ing
builtin/apply: make find_header() return -128 instead of die()ing
builtin/apply: make parse_chunk() return a negative integer on error
builtin/apply: make parse_single_patch() return -1 on error
builtin/apply: make parse_whitespace_option() return -1 instead of
die()ing
builtin/apply: make parse_ignorewhitespace_option() return -1 instead
of die()ing
builtin/apply: move init_apply_state() to apply.c
apply: make init_apply_state() return -1 instead of exit()ing
builtin/apply: make check_apply_state() return -1 instead of die()ing
builtin/apply: move check_apply_state() to apply.c
builtin/apply: make apply_all_patches() return 128 or 1 on error
builtin/apply: make parse_traditional_patch() return -1 on error
builtin/apply: make gitdiff_*() return 1 at end of header
builtin/apply: make gitdiff_*() return -1 on error
builtin/apply: change die_on_unsafe_path() to check_unsafe_path()
builtin/apply: make build_fake_ancestor() return -1 on error
builtin/apply: make remove_file() return -1 on error
builtin/apply: make add_conflicted_stages_file() return -1 on error
builtin/apply: make add_index_file() return -1 on error
builtin/apply: make create_file() return -1 on error
builtin/apply: make write_out_one_result() return -1 on error
builtin/apply: make write_out_results() return -1 on error
builtin/apply: make try_create_file() return -1 on error
builtin/apply: make create_one_file() return -1 on error
builtin/apply: rename option parsing functions
apply: rename and move opt constants to apply.h
Move libified code from builtin/apply.c to apply.{c,h}
apply: make some parsing functions static again
apply: use error_errno() where possible
apply: make it possible to silently apply
apply: don't print on stdout in verbosity_silent mode
usage: add set_warn_routine()
usage: add get_error_routine() and get_warn_routine()
apply: change error_routine when silent
apply: refactor `git apply` option parsing
apply: pass apply state to build_fake_ancestor()
apply: learn to use a different index file
builtin/am: use apply API in run_apply()
Makefile | 1 +
apply.c | 4988 ++++++++++++++++++++++++++++++++++++++++++++++++
apply.h | 137 ++
builtin/am.c | 65 +-
builtin/apply.c | 4873 +---------------------------------------------
git-compat-util.h | 3 +
t/t4012-diff-binary.sh | 4 +-
t/t4254-am-corrupt.sh | 2 +-
usage.c | 15 +
9 files changed, 5205 insertions(+), 4883 deletions(-)
create mode 100644 apply.c
create mode 100644 apply.h
--
2.10.0.41.g9df52c3
^ permalink raw reply
* [PATCH v14 01/41] apply: make some names more specific
From: Christian Couder @ 2016-09-04 20:17 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Ævar Arnfjörð Bjarmason,
Karsten Blees, Nguyen Thai Ngoc Duy, Stefan Beller, Eric Sunshine,
Ramsay Jones, Johannes Sixt, René Scharfe, Stefan Naewe,
Christian Couder
In-Reply-To: <20160904201833.21676-1-chriscool@tuxfamily.org>
To prepare for some structs and constants being moved from
builtin/apply.c to apply.h, we should give them some more
specific names to avoid possible name collisions in the global
namespace.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
builtin/apply.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/builtin/apply.c b/builtin/apply.c
index 1a488f9..ab8f0bd 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -21,7 +21,7 @@
#include "ll-merge.h"
#include "rerere.h"
-enum ws_error_action {
+enum apply_ws_error_action {
nowarn_ws_error,
warn_on_ws_error,
die_on_ws_error,
@@ -29,7 +29,7 @@ enum ws_error_action {
};
-enum ws_ignore {
+enum apply_ws_ignore {
ignore_ws_none,
ignore_ws_change
};
@@ -45,8 +45,8 @@ enum ws_ignore {
* See also "struct string_list symlink_changes" in "struct
* apply_state".
*/
-#define SYMLINK_GOES_AWAY 01
-#define SYMLINK_IN_RESULT 02
+#define APPLY_SYMLINK_GOES_AWAY 01
+#define APPLY_SYMLINK_IN_RESULT 02
struct apply_state {
const char *prefix;
@@ -110,8 +110,8 @@ struct apply_state {
struct string_list fn_table;
/* These control whitespace errors */
- enum ws_error_action ws_error_action;
- enum ws_ignore ws_ignore_action;
+ enum apply_ws_error_action ws_error_action;
+ enum apply_ws_ignore ws_ignore_action;
const char *whitespace_option;
int whitespace_error;
int squelch_whitespace_errors;
@@ -3750,11 +3750,11 @@ static void prepare_symlink_changes(struct apply_state *state, struct patch *pat
if ((patch->old_name && S_ISLNK(patch->old_mode)) &&
(patch->is_rename || patch->is_delete))
/* the symlink at patch->old_name is removed */
- register_symlink_changes(state, patch->old_name, SYMLINK_GOES_AWAY);
+ register_symlink_changes(state, patch->old_name, APPLY_SYMLINK_GOES_AWAY);
if (patch->new_name && S_ISLNK(patch->new_mode))
/* the symlink at patch->new_name is created or remains */
- register_symlink_changes(state, patch->new_name, SYMLINK_IN_RESULT);
+ register_symlink_changes(state, patch->new_name, APPLY_SYMLINK_IN_RESULT);
}
}
@@ -3769,9 +3769,9 @@ static int path_is_beyond_symlink_1(struct apply_state *state, struct strbuf *na
break;
name->buf[name->len] = '\0';
change = check_symlink_changes(state, name->buf);
- if (change & SYMLINK_IN_RESULT)
+ if (change & APPLY_SYMLINK_IN_RESULT)
return 1;
- if (change & SYMLINK_GOES_AWAY)
+ if (change & APPLY_SYMLINK_GOES_AWAY)
/*
* This cannot be "return 0", because we may
* see a new one created at a higher level.
--
2.10.0.41.g9df52c3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox