* [PATCH v4 11/15] refs.c: make get_main_ref_store() public and use it
From: Nguyễn Thái Ngọc Duy @ 2017-02-18 13:32 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Michael Haggerty, Johannes Schindelin,
Ramsay Jones, Stefan Beller, novalis,
Nguyễn Thái Ngọc Duy
In-Reply-To: <20170218133303.3682-1-pclouds@gmail.com>
get_ref_store() will soon be renamed to get_submodule_ref_store().
Together with future get_worktree_ref_store(), the three functions
provide an appropriate ref store for different operation modes. New APIs
will be added to operate directly on ref stores.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
refs.c | 36 ++++++++++++++++++------------------
refs.h | 2 ++
2 files changed, 20 insertions(+), 18 deletions(-)
diff --git a/refs.c b/refs.c
index 8b640bd05..1b60e6180 100644
--- a/refs.c
+++ b/refs.c
@@ -1308,7 +1308,7 @@ const char *resolve_ref_recursively(struct ref_store *refs,
/* backend functions */
int refs_init_db(struct strbuf *err)
{
- struct ref_store *refs = get_ref_store(NULL);
+ struct ref_store *refs = get_main_ref_store();
return refs->be->init_db(refs, err);
}
@@ -1316,7 +1316,7 @@ int refs_init_db(struct strbuf *err)
const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
unsigned char *sha1, int *flags)
{
- return resolve_ref_recursively(get_ref_store(NULL), refname,
+ return resolve_ref_recursively(get_main_ref_store(), refname,
resolve_flags, sha1, flags);
}
@@ -1439,7 +1439,7 @@ static struct ref_store *ref_store_init(const char *submodule)
return refs;
}
-static struct ref_store *get_main_ref_store(void)
+struct ref_store *get_main_ref_store(void)
{
struct ref_store *refs;
@@ -1488,14 +1488,14 @@ void base_ref_store_init(struct ref_store *refs,
/* backend functions */
int pack_refs(unsigned int flags)
{
- struct ref_store *refs = get_ref_store(NULL);
+ struct ref_store *refs = get_main_ref_store();
return refs->be->pack_refs(refs, flags);
}
int peel_ref(const char *refname, unsigned char *sha1)
{
- struct ref_store *refs = get_ref_store(NULL);
+ struct ref_store *refs = get_main_ref_store();
return refs->be->peel_ref(refs, refname, sha1);
}
@@ -1503,7 +1503,7 @@ int peel_ref(const char *refname, unsigned char *sha1)
int create_symref(const char *ref_target, const char *refs_heads_master,
const char *logmsg)
{
- struct ref_store *refs = get_ref_store(NULL);
+ struct ref_store *refs = get_main_ref_store();
return refs->be->create_symref(refs, ref_target, refs_heads_master,
logmsg);
@@ -1512,7 +1512,7 @@ int create_symref(const char *ref_target, const char *refs_heads_master,
int ref_transaction_commit(struct ref_transaction *transaction,
struct strbuf *err)
{
- struct ref_store *refs = get_ref_store(NULL);
+ struct ref_store *refs = get_main_ref_store();
return refs->be->transaction_commit(refs, transaction, err);
}
@@ -1522,14 +1522,14 @@ int verify_refname_available(const char *refname,
const struct string_list *skip,
struct strbuf *err)
{
- struct ref_store *refs = get_ref_store(NULL);
+ struct ref_store *refs = get_main_ref_store();
return refs->be->verify_refname_available(refs, refname, extra, skip, err);
}
int for_each_reflog(each_ref_fn fn, void *cb_data)
{
- struct ref_store *refs = get_ref_store(NULL);
+ struct ref_store *refs = get_main_ref_store();
struct ref_iterator *iter;
iter = refs->be->reflog_iterator_begin(refs);
@@ -1540,7 +1540,7 @@ int for_each_reflog(each_ref_fn fn, void *cb_data)
int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn,
void *cb_data)
{
- struct ref_store *refs = get_ref_store(NULL);
+ struct ref_store *refs = get_main_ref_store();
return refs->be->for_each_reflog_ent_reverse(refs, refname,
fn, cb_data);
@@ -1549,14 +1549,14 @@ int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn,
int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn,
void *cb_data)
{
- struct ref_store *refs = get_ref_store(NULL);
+ struct ref_store *refs = get_main_ref_store();
return refs->be->for_each_reflog_ent(refs, refname, fn, cb_data);
}
int reflog_exists(const char *refname)
{
- struct ref_store *refs = get_ref_store(NULL);
+ struct ref_store *refs = get_main_ref_store();
return refs->be->reflog_exists(refs, refname);
}
@@ -1564,14 +1564,14 @@ int reflog_exists(const char *refname)
int safe_create_reflog(const char *refname, int force_create,
struct strbuf *err)
{
- struct ref_store *refs = get_ref_store(NULL);
+ struct ref_store *refs = get_main_ref_store();
return refs->be->create_reflog(refs, refname, force_create, err);
}
int delete_reflog(const char *refname)
{
- struct ref_store *refs = get_ref_store(NULL);
+ struct ref_store *refs = get_main_ref_store();
return refs->be->delete_reflog(refs, refname);
}
@@ -1583,7 +1583,7 @@ int reflog_expire(const char *refname, const unsigned char *sha1,
reflog_expiry_cleanup_fn cleanup_fn,
void *policy_cb_data)
{
- struct ref_store *refs = get_ref_store(NULL);
+ struct ref_store *refs = get_main_ref_store();
return refs->be->reflog_expire(refs, refname, sha1, flags,
prepare_fn, should_prune_fn,
@@ -1593,21 +1593,21 @@ int reflog_expire(const char *refname, const unsigned char *sha1,
int initial_ref_transaction_commit(struct ref_transaction *transaction,
struct strbuf *err)
{
- struct ref_store *refs = get_ref_store(NULL);
+ struct ref_store *refs = get_main_ref_store();
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);
+ struct ref_store *refs = get_main_ref_store();
return refs->be->delete_refs(refs, refnames, flags);
}
int rename_ref(const char *oldref, const char *newref, const char *logmsg)
{
- struct ref_store *refs = get_ref_store(NULL);
+ struct ref_store *refs = get_main_ref_store();
return refs->be->rename_ref(refs, oldref, newref, logmsg);
}
diff --git a/refs.h b/refs.h
index 9fbff90e7..a35b687d7 100644
--- a/refs.h
+++ b/refs.h
@@ -555,4 +555,6 @@ int reflog_expire(const char *refname, const unsigned char *sha1,
int ref_storage_backend_exists(const char *name);
+struct ref_store *get_main_ref_store(void);
+
#endif /* REFS_H */
--
2.11.0.157.gd943d85
^ permalink raw reply related
* [PATCH v4 12/15] path.c: move some code out of strbuf_git_path_submodule()
From: Nguyễn Thái Ngọc Duy @ 2017-02-18 13:33 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Michael Haggerty, Johannes Schindelin,
Ramsay Jones, Stefan Beller, novalis,
Nguyễn Thái Ngọc Duy
In-Reply-To: <20170218133303.3682-1-pclouds@gmail.com>
refs is learning to avoid path rewriting that is done by
strbuf_git_path_submodule(). Factor out this code so it could be reused
by refs*
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
path.c | 34 +++++++---------------------------
submodule.c | 31 +++++++++++++++++++++++++++++++
submodule.h | 1 +
3 files changed, 39 insertions(+), 27 deletions(-)
diff --git a/path.c b/path.c
index efcedafba..3451d2916 100644
--- a/path.c
+++ b/path.c
@@ -475,35 +475,16 @@ const char *worktree_git_path(const struct worktree *wt, const char *fmt, ...)
static int do_submodule_path(struct strbuf *buf, const char *path,
const char *fmt, va_list args)
{
- const char *git_dir;
struct strbuf git_submodule_common_dir = STRBUF_INIT;
struct strbuf git_submodule_dir = STRBUF_INIT;
- const struct submodule *sub;
- int err = 0;
+ int ret;
- strbuf_addstr(buf, path);
- strbuf_complete(buf, '/');
- strbuf_addstr(buf, ".git");
-
- git_dir = read_gitfile(buf->buf);
- if (git_dir) {
- strbuf_reset(buf);
- strbuf_addstr(buf, git_dir);
- }
- if (!is_git_directory(buf->buf)) {
- gitmodules_config();
- sub = submodule_from_path(null_sha1, path);
- if (!sub) {
- err = SUBMODULE_PATH_ERR_NOT_CONFIGURED;
- goto cleanup;
- }
- strbuf_reset(buf);
- strbuf_git_path(buf, "%s/%s", "modules", sub->name);
- }
-
- strbuf_addch(buf, '/');
- strbuf_addbuf(&git_submodule_dir, buf);
+ ret = submodule_to_gitdir(&git_submodule_dir, path);
+ if (ret)
+ goto cleanup;
+ strbuf_complete(&git_submodule_dir, '/');
+ strbuf_addbuf(buf, &git_submodule_dir);
strbuf_vaddf(buf, fmt, args);
if (get_common_dir_noenv(&git_submodule_common_dir, git_submodule_dir.buf))
@@ -514,8 +495,7 @@ static int do_submodule_path(struct strbuf *buf, const char *path,
cleanup:
strbuf_release(&git_submodule_dir);
strbuf_release(&git_submodule_common_dir);
-
- return err;
+ return ret;
}
char *git_pathdup_submodule(const char *path, const char *fmt, ...)
diff --git a/submodule.c b/submodule.c
index 3b98766a6..36b8d1d11 100644
--- a/submodule.c
+++ b/submodule.c
@@ -1514,3 +1514,34 @@ void absorb_git_dir_into_superproject(const char *prefix,
strbuf_release(&sb);
}
}
+
+int submodule_to_gitdir(struct strbuf *buf, const char *submodule)
+{
+ const struct submodule *sub;
+ const char *git_dir;
+ int ret = 0;
+
+ strbuf_reset(buf);
+ strbuf_addstr(buf, submodule);
+ strbuf_complete(buf, '/');
+ strbuf_addstr(buf, ".git");
+
+ git_dir = read_gitfile(buf->buf);
+ if (git_dir) {
+ strbuf_reset(buf);
+ strbuf_addstr(buf, git_dir);
+ }
+ if (!is_git_directory(buf->buf)) {
+ gitmodules_config();
+ sub = submodule_from_path(null_sha1, submodule);
+ if (!sub) {
+ ret = -1;
+ goto cleanup;
+ }
+ strbuf_reset(buf);
+ strbuf_git_path(buf, "%s/%s", "modules", sub->name);
+ }
+
+cleanup:
+ return ret;
+}
diff --git a/submodule.h b/submodule.h
index 05ab674f0..fc3d0303e 100644
--- a/submodule.h
+++ b/submodule.h
@@ -81,6 +81,7 @@ extern int push_unpushed_submodules(struct sha1_array *commits,
int dry_run);
extern void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir);
extern int parallel_submodules(void);
+int submodule_to_gitdir(struct strbuf *buf, const char *submodule);
/*
* Prepare the "env_array" parameter of a "struct child_process" for executing
--
2.11.0.157.gd943d85
^ permalink raw reply related
* [PATCH v4 13/15] refs: move submodule code out of files-backend.c
From: Nguyễn Thái Ngọc Duy @ 2017-02-18 13:33 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Michael Haggerty, Johannes Schindelin,
Ramsay Jones, Stefan Beller, novalis,
Nguyễn Thái Ngọc Duy
In-Reply-To: <20170218133303.3682-1-pclouds@gmail.com>
files-backend is now initialized with a $GIT_DIR. Converting a submodule
path to where real submodule gitdir is located is done in get_ref_store().
The new code in init_submodule_ref_store() is basically a copy of
strbuf_git_path_submodule().
This gives a slight performance improvement for submodules since we
don't convert submodule path to gitdir at every backend call like
before. We pay that once at ref-store creation.
More cleanup in files_downcast() follows shortly. It's separate to keep
noises from this patch.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
refs.c | 18 +++++++++++++-----
refs/files-backend.c | 24 +++++++-----------------
refs/refs-internal.h | 6 +++---
3 files changed, 23 insertions(+), 25 deletions(-)
diff --git a/refs.c b/refs.c
index 1b60e6180..8035c3ea7 100644
--- a/refs.c
+++ b/refs.c
@@ -9,6 +9,7 @@
#include "refs/refs-internal.h"
#include "object.h"
#include "tag.h"
+#include "submodule.h"
/*
* List of all available backends
@@ -1424,9 +1425,9 @@ static void register_submodule_ref_store(struct ref_store *refs,
/*
* Create, record, and return a ref_store instance for the specified
- * submodule (or the main repository if submodule is NULL).
+ * gitdir (or the main repository if gitdir is NULL).
*/
-static struct ref_store *ref_store_init(const char *submodule)
+static struct ref_store *ref_store_init(const char *gitdir)
{
const char *be_name = "files";
struct ref_storage_be *be = find_ref_storage_backend(be_name);
@@ -1435,7 +1436,7 @@ static struct ref_store *ref_store_init(const char *submodule)
if (!be)
die("BUG: reference backend %s is unknown", be_name);
- refs = be->init(submodule);
+ refs = be->init(gitdir);
return refs;
}
@@ -1460,6 +1461,7 @@ struct ref_store *get_ref_store(const char *submodule)
{
struct strbuf submodule_sb = STRBUF_INIT;
struct ref_store *refs;
+ int ret;
if (!submodule || !*submodule) {
return get_main_ref_store();
@@ -1470,8 +1472,14 @@ struct ref_store *get_ref_store(const char *submodule)
return refs;
strbuf_addstr(&submodule_sb, submodule);
- if (is_nonbare_repository_dir(&submodule_sb))
- refs = ref_store_init(submodule);
+ ret = is_nonbare_repository_dir(&submodule_sb);
+ strbuf_release(&submodule_sb);
+ if (!ret)
+ return refs;
+
+ ret = submodule_to_gitdir(&submodule_sb, submodule);
+ if (!ret)
+ refs = ref_store_init(submodule_sb.buf);
strbuf_release(&submodule_sb);
if (refs)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index dbcaf9bda..529c80af1 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -917,13 +917,6 @@ struct packed_ref_cache {
struct files_ref_store {
struct ref_store base;
- /*
- * The name of the submodule represented by this object, or
- * NULL if it represents the main repository's reference
- * store:
- */
- const char *submodule;
-
struct strbuf gitdir;
struct strbuf gitcommondir;
@@ -945,11 +938,8 @@ static void files_path(struct files_ref_store *refs, struct strbuf *sb,
va_start(vap, fmt);
strbuf_vaddf(&tmp, fmt, vap);
va_end(vap);
- if (refs->submodule) {
- strbuf_git_path_submodule(sb, refs->submodule,
- "%s", tmp.buf);
- } else if (!strcmp(tmp.buf, "packed-refs") ||
- !strcmp(tmp.buf, "logs")) { /* non refname path */
+ if (!strcmp(tmp.buf, "packed-refs") || !strcmp(tmp.buf, "logs")) {
+ /* non refname path */
strbuf_addf(sb, "%s/%s", refs->gitcommondir.buf, tmp.buf);
} else if (skip_prefix(tmp.buf, "logs/", &ref)) { /* reflog */
if (is_per_worktree_ref(ref))
@@ -1018,7 +1008,7 @@ 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 ref_store *files_ref_store_create(const char *submodule)
+static struct ref_store *files_ref_store_create(const char *gitdir)
{
struct files_ref_store *refs = xcalloc(1, sizeof(*refs));
struct ref_store *ref_store = (struct ref_store *)refs;
@@ -1028,8 +1018,9 @@ static struct ref_store *files_ref_store_create(const char *submodule)
strbuf_init(&refs->gitdir, 0);
strbuf_init(&refs->gitcommondir, 0);
- if (submodule) {
- refs->submodule = xstrdup(submodule);
+ if (gitdir) {
+ strbuf_addstr(&refs->gitdir, gitdir);
+ get_common_dir_noenv(&refs->gitcommondir, gitdir);
} else {
strbuf_addstr(&refs->gitdir, get_git_dir());
strbuf_addstr(&refs->gitcommondir, get_git_common_dir());
@@ -1045,8 +1036,7 @@ static struct ref_store *files_ref_store_create(const char *submodule)
static void files_assert_main_repository(struct files_ref_store *refs,
const char *caller)
{
- if (refs->submodule)
- die("BUG: %s called for a submodule", caller);
+ /* This function is to be deleted in the next patch */
}
/*
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index 8c5febf54..3ef020acf 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -482,12 +482,12 @@ 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
+ * Initialize the ref_store for the specified gitdir, or for the
+ * current repository if gitdir == 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 struct ref_store *ref_store_init_fn(const char *gitdir);
typedef int ref_init_db_fn(struct ref_store *refs, struct strbuf *err);
--
2.11.0.157.gd943d85
^ permalink raw reply related
* [PATCH v4 14/15] files-backend: remove submodule_allowed from files_downcast()
From: Nguyễn Thái Ngọc Duy @ 2017-02-18 13:33 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Michael Haggerty, Johannes Schindelin,
Ramsay Jones, Stefan Beller, novalis,
Nguyễn Thái Ngọc Duy
In-Reply-To: <20170218133303.3682-1-pclouds@gmail.com>
Since submodule or not is irrelevant to files-backend after the last
patch, remove the parameter from files_downcast() and kill
files_assert_main_repository().
PS. This implies that all ref operations are allowed for submodules. But
we may need to look more closely to see if that's really true...
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
refs/files-backend.c | 70 ++++++++++++++++------------------------------------
1 file changed, 21 insertions(+), 49 deletions(-)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 529c80af1..b8ccf4e47 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1030,24 +1030,13 @@ static struct ref_store *files_ref_store_create(const char *gitdir)
}
/*
- * Die if refs is for a submodule (i.e., not for the main repository).
- * caller is used in any necessary error messages.
- */
-static void files_assert_main_repository(struct files_ref_store *refs,
- const char *caller)
-{
- /* This function is to be deleted in the next patch */
-}
-
-/*
* 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)
+static struct files_ref_store *files_downcast(struct ref_store *ref_store,
+ const char *caller)
{
struct files_ref_store *refs;
@@ -1057,9 +1046,6 @@ static struct files_ref_store *files_downcast(
refs = (struct files_ref_store *)ref_store;
- if (!submodule_allowed)
- files_assert_main_repository(refs, caller);
-
return refs;
}
@@ -1395,7 +1381,7 @@ static int files_read_raw_ref(struct ref_store *ref_store,
struct strbuf *referent, unsigned int *type)
{
struct files_ref_store *refs =
- files_downcast(ref_store, 1, "read_raw_ref");
+ files_downcast(ref_store, "read_raw_ref");
struct strbuf sb_contents = STRBUF_INIT;
struct strbuf sb_path = STRBUF_INIT;
const char *path;
@@ -1588,7 +1574,6 @@ static int lock_raw_ref(struct files_ref_store *refs,
int ret = TRANSACTION_GENERIC_ERROR;
assert(err);
- files_assert_main_repository(refs, "lock_raw_ref");
*type = 0;
@@ -1812,7 +1797,7 @@ static enum peel_status peel_entry(struct ref_entry *entry, int repeel)
static int files_peel_ref(struct ref_store *ref_store,
const char *refname, unsigned char *sha1)
{
- struct files_ref_store *refs = files_downcast(ref_store, 0, "peel_ref");
+ struct files_ref_store *refs = files_downcast(ref_store, "peel_ref");
int flag;
unsigned char base[20];
@@ -1921,7 +1906,7 @@ static struct ref_iterator *files_ref_iterator_begin(
const char *prefix, unsigned int flags)
{
struct files_ref_store *refs =
- files_downcast(ref_store, 1, "ref_iterator_begin");
+ files_downcast(ref_store, "ref_iterator_begin");
struct ref_dir *loose_dir, *packed_dir;
struct ref_iterator *loose_iter, *packed_iter;
struct files_ref_iterator *iter;
@@ -2059,7 +2044,6 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs,
int resolve_flags = RESOLVE_REF_NO_RECURSE;
int resolved;
- files_assert_main_repository(refs, "lock_ref_sha1_basic");
assert(err);
lock = xcalloc(1, sizeof(struct ref_lock));
@@ -2184,8 +2168,6 @@ static int lock_packed_refs(struct files_ref_store *refs, int flags)
struct strbuf sb = STRBUF_INIT;
int ret;
- files_assert_main_repository(refs, "lock_packed_refs");
-
if (!timeout_configured) {
git_config_get_int("core.packedrefstimeout", &timeout_value);
timeout_configured = 1;
@@ -2225,8 +2207,6 @@ static int commit_packed_refs(struct files_ref_store *refs)
int save_errno = 0;
FILE *out;
- files_assert_main_repository(refs, "commit_packed_refs");
-
if (!packed_ref_cache->lock)
die("internal error: packed-refs not locked");
@@ -2258,8 +2238,6 @@ static void rollback_packed_refs(struct files_ref_store *refs)
struct packed_ref_cache *packed_ref_cache =
get_packed_ref_cache(refs);
- files_assert_main_repository(refs, "rollback_packed_refs");
-
if (!packed_ref_cache->lock)
die("internal error: packed-refs not locked");
rollback_lock_file(packed_ref_cache->lock);
@@ -2420,7 +2398,7 @@ static void prune_refs(struct files_ref_store *refs, struct ref_to_prune *r)
static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)
{
struct files_ref_store *refs =
- files_downcast(ref_store, 0, "pack_refs");
+ files_downcast(ref_store, "pack_refs");
struct pack_refs_cb_data cbdata;
memset(&cbdata, 0, sizeof(cbdata));
@@ -2453,7 +2431,6 @@ static int repack_without_refs(struct files_ref_store *refs,
struct string_list_item *refname;
int ret, needs_repacking = 0, removed = 0;
- files_assert_main_repository(refs, "repack_without_refs");
assert(err);
/* Look for a packed ref */
@@ -2503,7 +2480,7 @@ static int files_delete_refs(struct ref_store *ref_store,
struct string_list *refnames, unsigned int flags)
{
struct files_ref_store *refs =
- files_downcast(ref_store, 0, "delete_refs");
+ files_downcast(ref_store, "delete_refs");
struct strbuf err = STRBUF_INIT;
int i, result = 0;
@@ -2615,7 +2592,7 @@ static int files_verify_refname_available(struct ref_store *ref_store,
struct strbuf *err)
{
struct files_ref_store *refs =
- files_downcast(ref_store, 1, "verify_refname_available");
+ files_downcast(ref_store, "verify_refname_available");
struct ref_dir *packed_refs = get_packed_refs(refs);
struct ref_dir *loose_refs = get_loose_refs(refs);
@@ -2640,7 +2617,7 @@ static int files_rename_ref(struct ref_store *ref_store,
const char *logmsg)
{
struct files_ref_store *refs =
- files_downcast(ref_store, 0, "rename_ref");
+ files_downcast(ref_store, "rename_ref");
unsigned char sha1[20], orig_sha1[20];
int flag = 0, logmoved = 0;
struct ref_lock *lock;
@@ -2883,7 +2860,7 @@ static int files_create_reflog(struct ref_store *ref_store,
struct strbuf *err)
{
struct files_ref_store *refs =
- files_downcast(ref_store, 0, "create_reflog");
+ files_downcast(ref_store, "create_reflog");
int fd;
if (log_ref_setup(refs, refname, force_create, &fd, err))
@@ -3014,8 +2991,6 @@ static int commit_ref_update(struct files_ref_store *refs,
const unsigned char *sha1, const char *logmsg,
struct strbuf *err)
{
- files_assert_main_repository(refs, "commit_ref_update");
-
clear_loose_ref_cache(refs);
if (files_log_ref_write(refs, lock->ref_name, lock->old_oid.hash,
sha1, logmsg, 0, err)) {
@@ -3124,7 +3099,7 @@ static int files_create_symref(struct ref_store *ref_store,
const char *logmsg)
{
struct files_ref_store *refs =
- files_downcast(ref_store, 0, "create_symref");
+ files_downcast(ref_store, "create_symref");
struct strbuf err = STRBUF_INIT;
struct ref_lock *lock;
int ret;
@@ -3150,7 +3125,7 @@ int set_worktree_head_symref(const char *gitdir, const char *target)
* backends. This function needs to die.
*/
struct files_ref_store *refs =
- files_downcast(get_ref_store(NULL), 0, "set_head_symref");
+ files_downcast(get_ref_store(NULL), "set_head_symref");
static struct lock_file head_lock;
struct ref_lock *lock;
struct strbuf head_path = STRBUF_INIT;
@@ -3188,7 +3163,7 @@ static int files_reflog_exists(struct ref_store *ref_store,
const char *refname)
{
struct files_ref_store *refs =
- files_downcast(ref_store, 0, "reflog_exists");
+ files_downcast(ref_store, "reflog_exists");
struct strbuf sb = STRBUF_INIT;
struct stat st;
int ret;
@@ -3203,7 +3178,7 @@ static int files_delete_reflog(struct ref_store *ref_store,
const char *refname)
{
struct files_ref_store *refs =
- files_downcast(ref_store, 0, "delete_reflog");
+ files_downcast(ref_store, "delete_reflog");
struct strbuf sb = STRBUF_INIT;
int ret;
@@ -3258,7 +3233,7 @@ static int files_for_each_reflog_ent_reverse(struct ref_store *ref_store,
void *cb_data)
{
struct files_ref_store *refs =
- files_downcast(ref_store, 0, "for_each_reflog_ent_reverse");
+ files_downcast(ref_store, "for_each_reflog_ent_reverse");
struct strbuf sb = STRBUF_INIT;
FILE *logfp;
long pos;
@@ -3366,7 +3341,7 @@ static int files_for_each_reflog_ent(struct ref_store *ref_store,
each_reflog_ent_fn fn, void *cb_data)
{
struct files_ref_store *refs =
- files_downcast(ref_store, 0, "for_each_reflog_ent");
+ files_downcast(ref_store, "for_each_reflog_ent");
FILE *logfp;
struct strbuf sb = STRBUF_INIT;
int ret = 0;
@@ -3454,7 +3429,7 @@ static struct ref_iterator_vtable files_reflog_iterator_vtable = {
static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_store)
{
struct files_ref_store *refs =
- files_downcast(ref_store, 0, "reflog_iterator_begin");
+ files_downcast(ref_store, "reflog_iterator_begin");
struct files_reflog_iterator *iter = xcalloc(1, sizeof(*iter));
struct ref_iterator *ref_iterator = &iter->base;
struct strbuf sb = STRBUF_INIT;
@@ -3666,8 +3641,6 @@ static int lock_ref_for_update(struct files_ref_store *refs,
int ret;
struct ref_lock *lock;
- files_assert_main_repository(refs, "lock_ref_for_update");
-
if ((update->flags & REF_HAVE_NEW) && is_null_sha1(update->new_sha1))
update->flags |= REF_DELETING;
@@ -3792,7 +3765,7 @@ static int files_transaction_commit(struct ref_store *ref_store,
struct strbuf *err)
{
struct files_ref_store *refs =
- files_downcast(ref_store, 0, "ref_transaction_commit");
+ files_downcast(ref_store, "ref_transaction_commit");
int ret = 0, i;
struct string_list refs_to_delete = STRING_LIST_INIT_NODUP;
struct string_list_item *ref_to_delete;
@@ -4000,7 +3973,7 @@ static int files_initial_transaction_commit(struct ref_store *ref_store,
struct strbuf *err)
{
struct files_ref_store *refs =
- files_downcast(ref_store, 0, "initial_ref_transaction_commit");
+ files_downcast(ref_store, "initial_ref_transaction_commit");
int ret = 0, i;
struct string_list affected_refnames = STRING_LIST_INIT_NODUP;
@@ -4122,7 +4095,7 @@ static int files_reflog_expire(struct ref_store *ref_store,
void *policy_cb_data)
{
struct files_ref_store *refs =
- files_downcast(ref_store, 0, "reflog_expire");
+ files_downcast(ref_store, "reflog_expire");
static struct lock_file reflog_lock;
struct expire_reflog_cb cb;
struct ref_lock *lock;
@@ -4227,8 +4200,7 @@ static int files_reflog_expire(struct ref_store *ref_store,
static int files_init_db(struct ref_store *ref_store, struct strbuf *err)
{
- struct files_ref_store *refs =
- files_downcast(ref_store, 0, "init_db");
+ struct files_ref_store *refs = files_downcast(ref_store, "init_db");
struct strbuf sb = STRBUF_INIT;
/*
--
2.11.0.157.gd943d85
^ permalink raw reply related
* [PATCH v4 15/15] refs: rename get_ref_store() to get_submodule_ref_store() and make it public
From: Nguyễn Thái Ngọc Duy @ 2017-02-18 13:33 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Michael Haggerty, Johannes Schindelin,
Ramsay Jones, Stefan Beller, novalis,
Nguyễn Thái Ngọc Duy
In-Reply-To: <20170218133303.3682-1-pclouds@gmail.com>
This function is intended to replace *_submodule() refs API. It provides
a ref store for a specific submodule, which can be operated on by a new
set of refs API.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
refs.c | 12 ++++++++----
refs.h | 11 +++++++++++
refs/files-backend.c | 2 +-
refs/refs-internal.h | 12 ------------
4 files changed, 20 insertions(+), 17 deletions(-)
diff --git a/refs.c b/refs.c
index 8035c3ea7..bc2247b59 100644
--- a/refs.c
+++ b/refs.c
@@ -1165,7 +1165,7 @@ int head_ref(each_ref_fn fn, void *cb_data)
static int do_for_each_ref(const char *submodule, const char *prefix,
each_ref_fn fn, int trim, int flags, void *cb_data)
{
- struct ref_store *refs = get_ref_store(submodule);
+ struct ref_store *refs = get_submodule_ref_store(submodule);
struct ref_iterator *iter;
if (!refs)
@@ -1338,10 +1338,10 @@ int resolve_gitlink_ref(const char *submodule, const char *refname,
/* We need to strip off one or more trailing slashes */
char *stripped = xmemdupz(submodule, len);
- refs = get_ref_store(stripped);
+ refs = get_submodule_ref_store(stripped);
free(stripped);
} else {
- refs = get_ref_store(submodule);
+ refs = get_submodule_ref_store(submodule);
}
if (!refs)
@@ -1457,13 +1457,17 @@ struct ref_store *get_main_ref_store(void)
return refs;
}
-struct ref_store *get_ref_store(const char *submodule)
+struct ref_store *get_submodule_ref_store(const char *submodule)
{
struct strbuf submodule_sb = STRBUF_INIT;
struct ref_store *refs;
int ret;
if (!submodule || !*submodule) {
+ /*
+ * FIXME: This case is ideally not allowed. But that
+ * can't happen until we clean up all the callers.
+ */
return get_main_ref_store();
}
diff --git a/refs.h b/refs.h
index a35b687d7..5bd065f12 100644
--- a/refs.h
+++ b/refs.h
@@ -556,5 +556,16 @@ int reflog_expire(const char *refname, const unsigned char *sha1,
int ref_storage_backend_exists(const char *name);
struct ref_store *get_main_ref_store(void);
+/*
+ * Return the ref_store instance for the specified submodule. For the
+ * main repository, use submodule==NULL; such a call cannot fail. For
+ * a submodule, the submodule must exist and be a nonbare repository,
+ * otherwise return NULL. If the requested reference store has not yet
+ * been initialized, initialize it first.
+ *
+ * For backwards compatibility, submodule=="" is treated the same as
+ * submodule==NULL.
+ */
+struct ref_store *get_submodule_ref_store(const char *submodule);
#endif /* REFS_H */
diff --git a/refs/files-backend.c b/refs/files-backend.c
index b8ccf4e47..603601f1b 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -3125,7 +3125,7 @@ int set_worktree_head_symref(const char *gitdir, const char *target)
* backends. This function needs to die.
*/
struct files_ref_store *refs =
- files_downcast(get_ref_store(NULL), "set_head_symref");
+ files_downcast(get_main_ref_store(), "set_head_symref");
static struct lock_file head_lock;
struct ref_lock *lock;
struct strbuf head_path = STRBUF_INIT;
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index 3ef020acf..ed6527ce1 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -640,18 +640,6 @@ struct ref_store {
void base_ref_store_init(struct ref_store *refs,
const struct ref_storage_be *be);
-/*
- * Return the ref_store instance for the specified submodule. For the
- * main repository, use submodule==NULL; such a call cannot fail. For
- * a submodule, the submodule must exist and be a nonbare repository,
- * otherwise return NULL. If the requested reference store has not yet
- * been initialized, initialize it first.
- *
- * For backwards compatibility, submodule=="" is treated the same as
- * submodule==NULL.
- */
-struct ref_store *get_ref_store(const char *submodule);
-
const char *resolve_ref_recursively(struct ref_store *refs,
const char *refname,
int resolve_flags,
--
2.11.0.157.gd943d85
^ permalink raw reply related
* Re: Git bisect does not find commit introducing the bug
From: Johannes Sixt @ 2017-02-18 14:18 UTC (permalink / raw)
To: Alex Hoffman; +Cc: Stephan Beyer, git
In-Reply-To: <CAMX8fZVkBU6M8fkUcRr69V97_NTSOGGmPB1U-ObhmVv3i6wQhg@mail.gmail.com>
Am 18.02.2017 um 12:15 schrieb Alex Hoffman:
> No one commented the fact, that I find this very confusing. Don't you
> find this confusing? I will underline, that 'git bisect good v.good'
> will fail if the commit 'v.good' is not a parent of the bad commit,
> meaning there MUST be at least a path between 'v.good' and 'v.bad',
> thus I would expect it looks on this path ONLY. Beside that, this is
> what I understand by 'binary search' (to search on this commit path).
But this is not how Git works. Git computes graph differences, i.e., it
subtracts from the commits reachable from v.bad those that are reachable
from v.good. This leaves more than just those on some path from v.good
to v.bad. And it should work this way. Consider this history:
--o--o--o--G--X
\ \
x--x--x--x--X--B--
When you find B bad and G good, than any one of the x or X may have
introduced the breakage, not just one of the X.
>> Correct. The assumption of bisection is that there is only one
>> transition between GOOD and BAD. By violating that assumption,
>> anything can happen.
>
> I did not find that in the manpage or did I miss it? Why would someone
> assume that the commit graph looks in a certain way?
There is no restriction in the commit graph. The only restriction,
actually assumption, is that there is *one* transition from good to bad
and no transition from bad to good. Otherwise, bisection cannot work.
> I assume, that
> 'git bisect' was not thought through and that it considers the first
> directed path between v.good and v.bad, instead of all paths (in my
> example graph there are two such paths). I will also underline that
> git bisect was designed to work with multiple good commits and one bad
> commit (also multiple paths), but probably NOT with multiple paths
> between the same pair of good and bad commits.
Oh, IMO git bisect was well thought through. If it considered just paths
from good to bad, it would not given the correct answer. See the example
history above. Bisect authors would not have deemed that sufficiently
good ;)
-- Hannes
^ permalink raw reply
* Re: Git bisect does not find commit introducing the bug
From: Alex Hoffman @ 2017-02-18 18:36 UTC (permalink / raw)
To: Johannes Sixt; +Cc: Stephan Beyer, git
In-Reply-To: <477d3533-d453-9499-e06e-72f45488d421@kdbg.org>
> But this is not how Git works. Git computes graph differences, i.e., it
> subtracts from the commits reachable from v.bad those that are reachable
> from v.good. This leaves more than just those on some path from v.good to
> v.bad. And it should work this way. Consider this history:
>
> --o--o--o--G--X
> \ \
> x--x--x--x--X--B--
>
> When you find B bad and G good, than any one of the x or X may have
> introduced the breakage, not just one of the X.
>
Thank you for clarifying how git bisect works. How did you find that
out? Did you check the source code? If that is not documented in the
man page may be it worth documenting it in order to avoid future
confusion for other users.
Let's consider your example with distinct names for nodes:
--o1--o2--o3--G--X1
\ \
x1--x2--x3--x4--X1--B--
It makes sense that git bisect is expecting a single transition, as
this is a precondition for a binary search to work. My definition of
"the transition" is a commit with at least one of its parents as a
good version, but the commit itself a bad version. I hope we agree
that git bisect's mission is to search for this transition (as I
suppose that most of people need such a functionality from git, if not
exactly from git bisect). How could be x1 or x3 be the transition, if
chances are that o1 is not a good version? Of course it would make
sense to me if bisect would check o1 whether good and only then to
check also x1-x3, but this is not what git makes (at least not in my
initial example).
If you consider that git bisect's mission is different from finding
the transition, could you please explain what exact commit git bisect
is supposed to return (ideally with terms from the graph theory) and
when it makes sense to return that? Because I do not see any sense in
looking in the path x1-x3 without knowing that those commits may be a
transition.
> Oh, IMO git bisect was well thought through. If it considered just paths
> from good to bad, it would not given the correct answer. See the example
> history above. Bisect authors would not have deemed that sufficiently good
You definitely convinced me that git MUST search more than only in the
paths between good and bad commits, as the good commit G does not have
to be the first good commit (thank you for that). My problem/confusion
is that it returns something that does not make sense to me, because
it does not make sure it returns a transition.
VG
PS: thank you for continuing this discussion.
^ permalink raw reply
* Re: [PATCH v3 02/19] builtin/diff-tree: convert to struct object_id
From: brian m. carlson @ 2017-02-18 19:12 UTC (permalink / raw)
To: Jeff King; +Cc: Ramsay Jones, git, Michael Haggerty, Junio C Hamano
In-Reply-To: <20170218031530.2bhlnjcukl4ybt6h@sigill.intra.peff.net>
[-- Attachment #1: Type: text/plain, Size: 1036 bytes --]
On Fri, Feb 17, 2017 at 10:15:31PM -0500, Jeff King wrote:
> So for this case, something like the patch below.
>
> Incidentally, there's an off-by-one in the original loop of
> stdin_diff_commit that reads past the end of the trailing NUL for the
> final sha1 on the line. The problem is the:
>
> pos += GIT_SHA1_HEXSZ + 1;
>
> which assumes we're slurping up the trailing space. This works in
> practice because the caller will only permit a string which had a
> newline (which it converted into a NUL).
>
> I suspect that function could be more aggressive about complaining about
> nonsense on the line, rather than silently ignoring it.
I'd come to basically the same patch, but I did pick up a few niceties
from your patch, like avoiding the off-by-one issue you mentioned above.
Can I place your sign-off on the resulting change?
--
brian m. carlson / brian with sandals: Houston, Texas, US
+1 832 623 2791 | https://www.crustytoothpaste.net/~bmc | My opinion only
OpenPGP: https://keybase.io/bk2204
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 868 bytes --]
^ permalink raw reply
* Re: Git bisect does not find commit introducing the bug
From: Christian Couder @ 2017-02-18 19:58 UTC (permalink / raw)
To: Alex Hoffman; +Cc: Johannes Sixt, Stephan Beyer, git
In-Reply-To: <CAMX8fZW2y+iPRfSbXVcHufbM+CsqgekS_0WnCEJ++=njy_TvKg@mail.gmail.com>
On Sat, Feb 18, 2017 at 7:36 PM, Alex Hoffman <spec@gal.ro> wrote:
>> But this is not how Git works. Git computes graph differences, i.e., it
>> subtracts from the commits reachable from v.bad those that are reachable
>> from v.good. This leaves more than just those on some path from v.good to
>> v.bad. And it should work this way. Consider this history:
>>
>> --o--o--o--G--X
>> \ \
>> x--x--x--x--X--B--
>>
>> When you find B bad and G good, than any one of the x or X may have
>> introduced the breakage, not just one of the X.
>>
>
> Thank you for clarifying how git bisect works. How did you find that
> out? Did you check the source code? If that is not documented in the
> man page may be it worth documenting it in order to avoid future
> confusion for other users.
At the end of the git-bisect man page (in the SEE ALSO section) there
is a link to https://github.com/git/git/blob/master/Documentation/git-bisect-lk2009.txt
which has a lot of details about how bisect works.
> Let's consider your example with distinct names for nodes:
>
> --o1--o2--o3--G--X1
> \ \
> x1--x2--x3--x4--X1--B--
>
> It makes sense that git bisect is expecting a single transition, as
> this is a precondition for a binary search to work. My definition of
> "the transition" is a commit with at least one of its parents as a
> good version, but the commit itself a bad version.
What if a commit C has one good parent A and one bad parent B?
Isn't it more likely that the first bad commit is B instead of C?
> I hope we agree
> that git bisect's mission is to search for this transition (as I
> suppose that most of people need such a functionality from git, if not
> exactly from git bisect).
The goal is to find the first bad commit, which is a commit that has
only good parents.
> How could be x1 or x3 be the transition, if
> chances are that o1 is not a good version?
As o1 is an ancestor of G, then o1 is considered good by the bisect algorithm.
If it was bad, it would means that there is a transition from bad to
good between o1 and G.
But when a good commit is an ancestor of the bad commit, git bisect
makes the assumption that there is no transition from bad to good in
the graph.
> Of course it would make
> sense to me if bisect would check o1 whether good and only then to
> check also x1-x3, but this is not what git makes (at least not in my
> initial example).
>
> If you consider that git bisect's mission is different from finding
> the transition, could you please explain what exact commit git bisect
> is supposed to return (ideally with terms from the graph theory) and
> when it makes sense to return that? Because I do not see any sense in
> looking in the path x1-x3 without knowing that those commits may be a
> transition.
I hope it makes sense with the above explanations.
>> Oh, IMO git bisect was well thought through. If it considered just paths
>> from good to bad, it would not given the correct answer. See the example
>> history above. Bisect authors would not have deemed that sufficiently good
>
> You definitely convinced me that git MUST search more than only in the
> paths between good and bad commits, as the good commit G does not have
> to be the first good commit (thank you for that). My problem/confusion
> is that it returns something that does not make sense to me, because
> it does not make sure it returns a transition.
git bisect makes some assumptions that are true most of the time, so
in practice it works well most of the time.
^ permalink raw reply
* Re: [PATCH v3 02/19] builtin/diff-tree: convert to struct object_id
From: Jeff King @ 2017-02-18 20:01 UTC (permalink / raw)
To: brian m. carlson, Ramsay Jones, git, Michael Haggerty,
Junio C Hamano
In-Reply-To: <20170218191217.thn3c2bympv2g7pm@genre.crustytoothpaste.net>
On Sat, Feb 18, 2017 at 07:12:18PM +0000, brian m. carlson wrote:
> On Fri, Feb 17, 2017 at 10:15:31PM -0500, Jeff King wrote:
> > So for this case, something like the patch below.
> >
> > Incidentally, there's an off-by-one in the original loop of
> > stdin_diff_commit that reads past the end of the trailing NUL for the
> > final sha1 on the line. The problem is the:
> >
> > pos += GIT_SHA1_HEXSZ + 1;
> >
> > which assumes we're slurping up the trailing space. This works in
> > practice because the caller will only permit a string which had a
> > newline (which it converted into a NUL).
> >
> > I suspect that function could be more aggressive about complaining about
> > nonsense on the line, rather than silently ignoring it.
>
> I'd come to basically the same patch, but I did pick up a few niceties
> from your patch, like avoiding the off-by-one issue you mentioned above.
> Can I place your sign-off on the resulting change?
Absolutely. Thanks for taking a look.
-Peff
^ permalink raw reply
* Re: [PATCH 0/5] A series of performance enhancements in the memihash and name-cache area
From: Junio C Hamano @ 2017-02-18 20:48 UTC (permalink / raw)
To: Jeff King; +Cc: Jeff Hostetler, Johannes Schindelin, git, Jeff Hostetler
In-Reply-To: <20170218062943.j2llxuuylqs2qemy@sigill.intra.peff.net>
Jeff King <peff@peff.net> writes:
> On Fri, Feb 17, 2017 at 09:58:21PM -0800, Junio C Hamano wrote:
>
>> Jeff Hostetler <git@jeffhostetler.com> writes:
>>
>> > I'll try to put together a before/after perf-test to better
>> > demonstrate this.
>>
>> I didn't pick up the series while watching these exchanges, as I
>> didn't know how quick your turnaround would be, but now a few days
>> have passed. Just to make sure we won't forget this topic, I'll
>> pick up these 5 patches in the meantime.
>
> Yeah, to be clear my question was not an objection, but mostly
> curiosity and interest.
Yes, it was very clear that it wasn't an objection.
But the other Jeff sounded like a follow-up was to follow shortly if
not imminent so I decided to allocate my time on other topics still
only on the list first while waiting to see what happens.
^ permalink raw reply
* Re: Git bisect does not find commit introducing the bug
From: Philip Oakley @ 2017-02-18 22:10 UTC (permalink / raw)
To: Alex Hoffman, Johannes Sixt; +Cc: Stephan Beyer, git
In-Reply-To: <CAMX8fZW2y+iPRfSbXVcHufbM+CsqgekS_0WnCEJ++=njy_TvKg@mail.gmail.com>
From: "Alex Hoffman" <spec@gal.ro>
>> But this is not how Git works. Git computes graph differences, i.e., it
>> subtracts from the commits reachable from v.bad those that are reachable
>> from v.good. This leaves more than just those on some path from v.good to
>> v.bad. And it should work this way. Consider this history:
>>
>> --o--o--o--G--X
>> \ \
>> x--x--x--x--X--B--
>>
>> When you find B bad and G good, than any one of the x or X may have
>> introduced the breakage, not just one of the X.
>>
>
> Thank you for clarifying how git bisect works. How did you find that
> out? Did you check the source code? If that is not documented in the
> man page may be it worth documenting it in order to avoid future
> confusion for other users.
Any suggestions for improving the documentation are always worthwhile. As
someone who asked, what extra info would have helped?
Even beetter if it looks like a patch ;-)
>
> Let's consider your example with distinct names for nodes:
>
> --o1--o2--o3--G--X1
> \ \
> x1--x2--x3--x4--X1--B--
>
> It makes sense that git bisect is expecting a single transition, as
> this is a precondition for a binary search to work. My definition of
> "the transition" is a commit with at least one of its parents as a
> good version, but the commit itself a bad version. I hope we agree
> that git bisect's mission is to search for this transition (as I
> suppose that most of people need such a functionality from git, if not
> exactly from git bisect). How could be x1 or x3 be the transition, if
> chances are that o1 is not a good version? Of course it would make
> sense to me if bisect would check o1 whether good and only then to
> check also x1-x3, but this is not what git makes (at least not in my
> initial example).
>
> If you consider that git bisect's mission is different from finding
> the transition, could you please explain what exact commit git bisect
> is supposed to return (ideally with terms from the graph theory) and
> when it makes sense to return that? Because I do not see any sense in
> looking in the path x1-x3 without knowing that those commits may be a
> transition.
>
>
>> Oh, IMO git bisect was well thought through. If it considered just paths
>> from good to bad, it would not given the correct answer. See the example
>> history above. Bisect authors would not have deemed that sufficiently
>> good
>
> You definitely convinced me that git MUST search more than only in the
> paths between good and bad commits, as the good commit G does not have
> to be the first good commit (thank you for that). My problem/confusion
> is that it returns something that does not make sense to me, because
> it does not make sure it returns a transition.
>
> VG
>
> PS: thank you for continuing this discussion.
>
--
Philip
^ permalink raw reply
* Re: Git bisect does not find commit introducing the bug
From: Hilco Wijbenga @ 2017-02-18 22:36 UTC (permalink / raw)
To: Alex Hoffman; +Cc: Johannes Sixt, Stephan Beyer, Git Users
In-Reply-To: <CAMX8fZW2y+iPRfSbXVcHufbM+CsqgekS_0WnCEJ++=njy_TvKg@mail.gmail.com>
On 18 February 2017 at 10:36, Alex Hoffman <spec@gal.ro> wrote:
> You definitely convinced me that git MUST search more than only in the
> paths between good and bad commits, as the good commit G does not have
> to be the first good commit (thank you for that). My problem/confusion
> is that it returns something that does not make sense to me, because
> it does not make sure it returns a transition.
If multiple transitions from GOOD to BAD happen, then I don't see how
binary search is useful/possible. The same is true for a simple list
of numbers, say, 1 5 6 2 3 4. You can't use binary search here because
you can't "throw away" all numbers to the left (or right) of your
pivot. Or am I missing your point?
^ permalink raw reply
* Re: Git bisect does not find commit introducing the bug
From: Johannes Sixt @ 2017-02-18 22:37 UTC (permalink / raw)
To: Alex Hoffman; +Cc: Stephan Beyer, git
In-Reply-To: <CAMX8fZW2y+iPRfSbXVcHufbM+CsqgekS_0WnCEJ++=njy_TvKg@mail.gmail.com>
Am 18.02.2017 um 19:36 schrieb Alex Hoffman:
> Let's consider your example with distinct names for nodes:
>
> --o1--o2--o3--G--X1
> \ \
> x1--x2--x3--x4--X2--B--
>
> It makes sense that git bisect is expecting a single transition, as
> this is a precondition for a binary search to work. My definition of
> "the transition" is a commit with at least one of its parents as a
> good version, but the commit itself a bad version.
But that is not the definition of transition that lets you pin-point the
breaking commit precisly. Assume x3 is the commit introducing the
breakage in the graph above. Even though you only know initially that G
is good and B is bad, would you not prefer to find x3 instead of X2? As
Christian said, a transition is when a commit is bad and all its parents
are good, and this definition lets you find x3.
> I hope we agree
> that git bisect's mission is to search for this transition (as I
> suppose that most of people need such a functionality from git, if not
> exactly from git bisect). How could be x1 or x3 be the transition, if
> chances are that o1 is not a good version?
By declaring G as good, it is implied that o1 is also good. If it is in
fact bad, the assumptions of git bisect are violated (because there
would be a transition from bad to good at o2, o3, or G), and anything
can happen.
> If you consider that git bisect's mission is different from finding
> the transition, could you please explain what exact commit git bisect
> is supposed to return (ideally with terms from the graph theory) and
> when it makes sense to return that? Because I do not see any sense in
> looking in the path x1-x3 without knowing that those commits may be a
> transition.
And I do not see a reason why git bisect should not look at those
commits. If x3 is the commit that broke my program, I do prefer to be
pointed at x3 rather than X2.
-- Hannes
^ permalink raw reply
* [PATCH] git-check-ref-format: fix typo in man page
From: Damien Regad @ 2017-02-18 22:47 UTC (permalink / raw)
To: git
---
Documentation/git-check-ref-format.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Documentation/git-check-ref-format.txt
b/Documentation/git-check-ref-format.txt
index 8611a99..377c85a 100644
--- a/Documentation/git-check-ref-format.txt
+++ b/Documentation/git-check-ref-format.txt
@@ -100,7 +100,7 @@ OPTIONS
--normalize::
Normalize 'refname' by removing any leading slash (`/`)
characters and collapsing runs of adjacent slashes between
- name components into a single slash. Iff the normalized
+ name components into a single slash. If the normalized
refname is valid then print it to standard output and exit
with a status of 0. (`--print` is a deprecated way to spell
`--normalize`.)
--
2.7.4
^ permalink raw reply related
* RE: [PATCH 0/5] A series of performance enhancements in the memihash and name-cache area
From: Jeff Hostetler @ 2017-02-18 23:52 UTC (permalink / raw)
To: Junio C Hamano, Jeff King
Cc: Jeff Hostetler, Johannes Schindelin, git@vger.kernel.org,
Jeff Hostetler
In-Reply-To: <xmqqk28nmdi4.fsf@gitster.mtv.corp.google.com>
> Jeff King <peff@peff.net> writes:
>
>> On Fri, Feb 17, 2017 at 09:58:21PM -0800, Junio C Hamano wrote:
>>
>>> Jeff Hostetler <git@jeffhostetler.com> writes:
>>>
>>> > I'll try to put together a before/after perf-test to better
>>> > demonstrate this.
>>>
>>> I didn't pick up the series while watching these exchanges, as I
>>> didn't know how quick your turnaround would be, but now a few days
>>> have passed. Just to make sure we won't forget this topic, I'll
>>> pick up these 5 patches in the meantime.
>>
>> Yeah, to be clear my question was not an objection, but mostly
>> curiosity and interest.
>
> Yes, it was very clear that it wasn't an objection.
>
> But the other Jeff sounded like a follow-up was to follow shortly if
> not imminent so I decided to allocate my time on other topics still
> only on the list first while waiting to see what happens.
Sorry, I was out of the office for a family emergency on Thursday
and Friday. Add to that the long weekend, and I won't get back around
to this until Tuesday or Wednesday at the earliest.
Jeff
^ permalink raw reply
* RE: [PATCH 0/5] A series of performance enhancements in the memihash and name-cache area
From: Jeff Hostetler @ 2017-02-19 0:02 UTC (permalink / raw)
To: Junio C Hamano, Jeff King
Cc: Jeff Hostetler, Johannes Schindelin, git@vger.kernel.org,
Jeff Hostetler
In-Reply-To: <xmqqvas8m499.fsf@gitster.mtv.corp.google.com>
From: Junio C Hamano [mailto:jch2355@gmail.com] On Behalf Of Junio C Hamano
> Jeff King <peff@peff.net> writes:
>> On Wed, Feb 15, 2017 at 09:27:53AM -0500, Jeff Hostetler wrote:
>>
>>> I have some informal numbers in a spreadsheet. I was seeing
>>> a 8-9% speed up on a status on my gigantic repo.
>>>
>>> I'll try to put together a before/after perf-test to better
>>> demonstrate this.
>>
>> Thanks. What I'm mostly curious about is how much each individual step
>> buys. Sometimes when doing a long optimization series, I find that some
>> of the optimizations make other ones somewhat redundant (e.g., if patch
>> 2 causes us to call the optimized code from patch 3 less often).
>
> I am curious too.
>
> To me 1/5 (reduction of redundant calls), 4/5 (correctly size the
> hash that would grow to a known size anyway) and 5/5 (take advantage
> of the fact that adjacent cache entries are often in the same
> directory) look like no brainers to take, regardless of the others
> (including themselves).
agreed.
> It is not clear to me if 3/5 (preload-index uses available cores to
> compute hashes) is an unconditional win (an operation that is
> pathspec limited may need hashes for only a small fraction of the
> index---would it still be a win to compute the hash for all entries
> upon loading the index, even if we are using otherwise-idel cores?).
I'm not sure about pathspec cases. What I was seeing was that during
the call to lazy_name_init_hash() was taking 30% of the time in
"git status" and 40% in "git add <one_file>". (Again this was on my
giant repo with a 450MB index).
> Of course 2/5 is a prerequisite step for 3/5 and 5/5, so if we want
> either of the latter two, we cannot avoid it.
jeff
^ permalink raw reply
* Re: [PATCH] git-check-ref-format: fix typo in man page
From: Jacob Keller @ 2017-02-19 0:17 UTC (permalink / raw)
To: Damien Regad; +Cc: Git mailing list
In-Reply-To: <c27d7861-b161-a3eb-fcfc-bf766fc7b20b@gmail.com>
On Sat, Feb 18, 2017 at 2:47 PM, Damien Regad <dregad@mantisbt.org> wrote:
>
> ---
> Documentation/git-check-ref-format.txt | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/Documentation/git-check-ref-format.txt
> b/Documentation/git-check-ref-format.txt
> index 8611a99..377c85a 100644
> --- a/Documentation/git-check-ref-format.txt
> +++ b/Documentation/git-check-ref-format.txt
> @@ -100,7 +100,7 @@ OPTIONS
> --normalize::
> Normalize 'refname' by removing any leading slash (`/`)
> characters and collapsing runs of adjacent slashes between
> - name components into a single slash. Iff the normalized
> + name components into a single slash. If the normalized
I think this is a good change, but I do know in some contexts, "Iff"
is used intentionally to mean "If and only if". It's somewhat unlikely
that's what was going on here, and I don't think we need to be that
pedantic in our help documentation anyway.
Thanks,
Jake
> refname is valid then print it to standard output and exit
> with a status of 0. (`--print` is a deprecated way to spell
> `--normalize`.)
> --
> 2.7.4
>
>
^ permalink raw reply
* RE: [PATCH 3/5] name-hash: precompute hash values during preload-index
From: Jeff Hostetler @ 2017-02-19 0:19 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git@vger.kernel.org, Johannes Schindelin, Jeff Hostetler
In-Reply-To: <xmqq37fcnj7v.fsf@gitster.mtv.corp.google.com>
From: Junio C Hamano [mailto:jch2355@gmail.com] On Behalf Of Junio C Hamano
>
> The fact that each preload_thread() still walks the index in-order
> makes me wonder if it may allow us to further optimize the "dir"
> part of the hash by passing the previous ce for which we already
> precomputed hash values. While the loop is iterating over the paths
> in the same directory, .dir component from the previous ce can be
> reused and .name component can "continue", no?
>
> It's possible that you already tried such an optimization and
> rejected it after finding that the cost of comparison of pathnames
> to tell if ce and previous ce are still in the same directory is
> more than unconditionally memihash() the directory part, and I am in
> no way saying that I found a missed optimization opportunity you
> must pursue. I am just being curious.
I looked at doing this, but I didn't think the complexity and overhead to
forward search for peers at the current level didn't warrant the limited gains.
(I was just looking at the complexity of clear_ce_flags_1() in unpack-trees.c
and how hard it has to look to find the end of the current directory and the
effect that that has on the recursion and it felt like too much work for the
potential gain.)
Whereas remembering the previous one was basically free. Granted, it only
helps us for adjacent files in the index, so it's not perfect, but gives us the
best bang for the buck.
Jeff
^ permalink raw reply
* Re: [PATCH] git-check-ref-format: fix typo in man page
From: Philip Oakley @ 2017-02-19 0:20 UTC (permalink / raw)
To: Damien Regad, git
In-Reply-To: <c27d7861-b161-a3eb-fcfc-bf766fc7b20b@gmail.com>
From: "Damien Regad" <dregad@mantisbt.org>
> ---
> Documentation/git-check-ref-format.txt | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/Documentation/git-check-ref-format.txt
> b/Documentation/git-check-ref-format.txt
> index 8611a99..377c85a 100644
> --- a/Documentation/git-check-ref-format.txt
> +++ b/Documentation/git-check-ref-format.txt
> @@ -100,7 +100,7 @@ OPTIONS
> --normalize::
> Normalize 'refname' by removing any leading slash (`/`)
> characters and collapsing runs of adjacent slashes between
> - name components into a single slash. Iff the normalized
> + name components into a single slash. If the normalized
> refname is valid then print it to standard output and exit
> with a status of 0. (`--print` is a deprecated way to spell
> `--normalize`.)
> --
Could that be an 'iff' == 'If and only if' (which is common in mathematics)?
Still could be spelling error though.
--
Philip
^ permalink raw reply
* Re: [PATCH] fetch: print an error when declining to request an unadvertised object
From: Matt McCutchen @ 2017-02-19 2:07 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <xmqq60kfezr9.fsf@gitster.mtv.corp.google.com>
On Sun, 2017-02-12 at 15:49 -0800, Junio C Hamano wrote:
> The fact that we have the above two choices tells me that a two-step
> approach may be an appropriate approach. [...]
> Even if you did only the first step, as long as the second step can
> be done without reverting what the first step did [*4*] by somebody
> who cares the "specific error" deeply enough, I am OK with that. Of
> course if you did both steps, that is fine by me as well ;-)
I appreciate the flexibility, but now that I've spent the time to
understand all the code involved, it would be a pity not to go for the
complete solution. New patch coming.
Matt
^ permalink raw reply
* [PATCH] fetch: print an error when declining to request an unadvertised object
From: Matt McCutchen @ 2017-02-19 1:55 UTC (permalink / raw)
To: git
In-Reply-To: <xmqq60kfezr9.fsf@gitster.mtv.corp.google.com>
Currently "git fetch REMOTE SHA1" silently exits 1 if the server doesn't
allow requests for unadvertised objects by sha1. The more common case
of requesting a nonexistent ref normally triggers a die() in
get_fetch_map, so "git fetch" wasn't bothering to check after the fetch
that it got all the refs it sought, like "git fetch-pack" does near the
end of cmd_fetch_pack.
Move the code from cmd_fetch_pack to a new function,
report_unmatched_refs, that is called by fetch_refs_via_pack as part of
"git fetch". Also, change filter_refs (which checks whether a request
for an unadvertised object should be sent to the server) to set a new
match status on the "struct ref" when the request is not allowed, and
have report_unmatched_refs check for this status and print a special
error message, "Server does not allow request for unadvertised object".
Finally, add a simple test case for "git fetch REMOTE SHA1".
Signed-off-by: Matt McCutchen <matt@mattmccutchen.net>
---
builtin/fetch-pack.c | 7 +------
fetch-pack.c | 51 ++++++++++++++++++++++++++++++++++++++-------------
fetch-pack.h | 9 +++++++++
remote.h | 9 +++++++--
t/t5516-fetch-push.sh | 3 ++-
transport.c | 14 +++++++++-----
6 files changed, 66 insertions(+), 27 deletions(-)
diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c
index cfe9e44..2a1c1c2 100644
--- a/builtin/fetch-pack.c
+++ b/builtin/fetch-pack.c
@@ -219,12 +219,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
* remote no-such-ref' would silently succeed without issuing
* an error.
*/
- for (i = 0; i < nr_sought; i++) {
- if (!sought[i] || sought[i]->matched)
- continue;
- error("no such remote ref %s", sought[i]->name);
- ret = 1;
- }
+ ret |= report_unmatched_refs(sought, nr_sought);
while (ref) {
printf("%s %s\n",
diff --git a/fetch-pack.c b/fetch-pack.c
index 601f077..f12bfcd 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -578,7 +578,7 @@ static void filter_refs(struct fetch_pack_args *args,
break; /* definitely do not have it */
else if (cmp == 0) {
keep = 1; /* definitely have it */
- sought[i]->matched = 1;
+ sought[i]->match_status = REF_MATCHED;
}
i++;
}
@@ -598,22 +598,24 @@ static void filter_refs(struct fetch_pack_args *args,
}
/* Append unmatched requests to the list */
- if ((allow_unadvertised_object_request &
- (ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1))) {
- for (i = 0; i < nr_sought; i++) {
- unsigned char sha1[20];
+ for (i = 0; i < nr_sought; i++) {
+ unsigned char sha1[20];
- ref = sought[i];
- if (ref->matched)
- continue;
- if (get_sha1_hex(ref->name, sha1) ||
- ref->name[40] != '\0' ||
- hashcmp(sha1, ref->old_oid.hash))
- continue;
+ ref = sought[i];
+ if (ref->match_status != REF_NOT_MATCHED)
+ continue;
+ if (get_sha1_hex(ref->name, sha1) ||
+ ref->name[40] != '\0' ||
+ hashcmp(sha1, ref->old_oid.hash))
+ continue;
- ref->matched = 1;
+ if ((allow_unadvertised_object_request &
+ (ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1))) {
+ ref->match_status = REF_MATCHED;
*newtail = copy_ref(ref);
newtail = &(*newtail)->next;
+ } else {
+ ref->match_status = REF_UNADVERTISED_NOT_ALLOWED;
}
}
*refs = newlist;
@@ -1094,3 +1096,26 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
clear_shallow_info(&si);
return ref_cpy;
}
+
+int report_unmatched_refs(struct ref **sought, int nr_sought)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < nr_sought; i++) {
+ if (!sought[i])
+ continue;
+ switch (sought[i]->match_status) {
+ case REF_MATCHED:
+ continue;
+ case REF_NOT_MATCHED:
+ error(_("no such remote ref %s"), sought[i]->name);
+ break;
+ case REF_UNADVERTISED_NOT_ALLOWED:
+ error(_("Server does not allow request for unadvertised object %s"),
+ sought[i]->name);
+ break;
+ }
+ ret = 1;
+ }
+ return ret;
+}
diff --git a/fetch-pack.h b/fetch-pack.h
index c912e3d..fd4d80e 100644
--- a/fetch-pack.h
+++ b/fetch-pack.h
@@ -45,4 +45,13 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
struct sha1_array *shallow,
char **pack_lockfile);
+/*
+ * Print an appropriate error message for each sought ref that wasn't
+ * matched. Return 0 if all sought refs were matched, otherwise 1.
+ *
+ * The type of "sought" should be "const struct ref *const *" but for
+ * http://stackoverflow.com/questions/5055655/double-pointer-const-correctness-warnings-in-c .
+ */
+int report_unmatched_refs(struct ref **sought, int nr_sought);
+
#endif
diff --git a/remote.h b/remote.h
index 9248811..0b9d8c4 100644
--- a/remote.h
+++ b/remote.h
@@ -89,8 +89,13 @@ struct ref {
force:1,
forced_update:1,
expect_old_sha1:1,
- deletion:1,
- matched:1;
+ deletion:1;
+
+ enum {
+ REF_NOT_MATCHED = 0, /* initial value */
+ REF_MATCHED,
+ REF_UNADVERTISED_NOT_ALLOWED
+ } match_status;
/*
* Order is important here, as we write to FETCH_HEAD
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 26b2caf..78f3b8e 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -1098,7 +1098,8 @@ test_expect_success 'fetch exact SHA1' '
test_must_fail git cat-file -t $the_commit &&
# fetching the hidden object should fail by default
- test_must_fail git fetch -v ../testrepo $the_commit:refs/heads/copy &&
+ test_must_fail git fetch -v ../testrepo $the_commit:refs/heads/copy 2>err &&
+ test_i18ngrep "Server does not allow request for unadvertised object" err &&
test_must_fail git rev-parse --verify refs/heads/copy &&
# the server side can allow it to succeed
diff --git a/transport.c b/transport.c
index 04e5d66..c377907 100644
--- a/transport.c
+++ b/transport.c
@@ -204,6 +204,7 @@ static struct ref *get_refs_via_connect(struct transport *transport, int for_pus
static int fetch_refs_via_pack(struct transport *transport,
int nr_heads, struct ref **to_fetch)
{
+ int ret = 0;
struct git_transport_data *data = transport->data;
struct ref *refs;
char *dest = xstrdup(transport->url);
@@ -241,19 +242,22 @@ static int fetch_refs_via_pack(struct transport *transport,
&transport->pack_lockfile);
close(data->fd[0]);
close(data->fd[1]);
- if (finish_connect(data->conn)) {
- free_refs(refs);
- refs = NULL;
- }
+ if (finish_connect(data->conn))
+ ret = -1;
data->conn = NULL;
data->got_remote_heads = 0;
data->options.self_contained_and_connected =
args.self_contained_and_connected;
+ if (refs == NULL)
+ ret = -1;
+ if (report_unmatched_refs(to_fetch, nr_heads))
+ ret = -1;
+
free_refs(refs_tmp);
free_refs(refs);
free(dest);
- return (refs ? 0 : -1);
+ return ret;
}
static int push_had_errors(struct ref *ref)
--
2.9.3
^ permalink raw reply related
* Re: [PATCH] fixup! bisect--helper: `bisect_next_check` & bisect_voc shell function in C
From: Junio C Hamano @ 2017-02-19 2:06 UTC (permalink / raw)
To: git; +Cc: René Scharfe, Johannes Schindelin, Pranit Bauva
In-Reply-To: <xmqqinodewdr.fsf@gitster.mtv.corp.google.com>
Junio C Hamano <gitster@pobox.com> writes:
> ...
> So, let's give Pranit a concrete "here is what we want to see
> squashed in", while you guys discuss peculiarity with various
> platforms and their system headers, which admittedly is a more
> interesting tangent ;-)
>
> There are early returns with "goto finish" even before _syn
> variables are first assigned to, so they would need to be
> initialized to NULL. The other two get their initial values
> right at the beginning, so they are OK.
>
> builtin/bisect--helper.c | 14 +++++---------
> 1 file changed, 5 insertions(+), 9 deletions(-)
While we are waiting for the topic to be fixed, I've tentatively
applied this on top to update 'pu', so Travis should now be happy
with 'pu' on Mac, too.
^ permalink raw reply
* Re: [PATCH] git-check-ref-format: fix typo in man page
From: Jeff King @ 2017-02-19 2:27 UTC (permalink / raw)
To: Philip Oakley; +Cc: Michael Haggerty, Damien Regad, git
In-Reply-To: <2116CBFFB78A482D8FA176BC680B3B9C@PhilipOakley>
On Sun, Feb 19, 2017 at 12:20:33AM -0000, Philip Oakley wrote:
> > Normalize 'refname' by removing any leading slash (`/`)
> > characters and collapsing runs of adjacent slashes between
> > - name components into a single slash. Iff the normalized
> > + name components into a single slash. If the normalized
> > refname is valid then print it to standard output and exit
> > with a status of 0. (`--print` is a deprecated way to spell
> > `--normalize`.)
> > --
>
> Could that be an 'iff' == 'If and only if' (which is common in mathematics)?
> Still could be spelling error though.
When we're not sure what the intent of a change is, a good first step is
to dig up the original commit via `git blame` or similar. In this case,
it comes from a40e6fb67 (Change check_refname_format() to reject
unnormalized refnames, 2011-09-15).
The commit message doesn't mention it (not that I really expected it
to), but it does tell you who the author is. And a good second step is
to cc them on the patch. :)
I suspect it _was_ intended as "iff" here. In my opinion, we probably
don't need to be so rigorous in this instance. However, I note that we
do not describe the "else" half of that "if". So maybe an overall
improvement would be something like:
If the normalized refname is valid then print it to standard output
and exit with a status of 0. Otherwise, exit with a non-zero status.
-Peff
^ permalink raw reply
* Re: difflame improvements
From: Edmundo Carmona Antoranz @ 2017-02-19 6:35 UTC (permalink / raw)
To: Jeff King; +Cc: Git List
In-Reply-To: <CAOc6etZxkspqafifjPTbRDoVBt0XuOLbhiuY9bFTD2Wjtxw-HQ@mail.gmail.com>
On Fri, Feb 17, 2017 at 1:01 AM, Edmundo Carmona Antoranz
<eantoranz@gmail.com> wrote:
> On Thu, Feb 16, 2017 at 11:17 PM, Jeff King <peff@peff.net> wrote:
>
>> This isn't difflame's fault; that's what "git blame" tells you about
>> that line. But since I already told difflame "v2.6.5..HEAD", it would
>> probably make sense to similarly limit the blame to that range. That
>> turns up a boundary commit for the line. Which is _also_ not helpful,
>> but at least the tool is telling me that the line came from before
>> v2.6.5, and I don't really need to care much about it.
>
>
> I'm running my own tests on difflame and I have a theory about "when"
> it breaks.... at least one of the cases when it breaks:
>
> Analysis for deleted lines is being driven by git blame --reverse.
> What I have noticed is that it "breaks" when blame --reverse drives
> the analysis into revisions where "treeish1" is not part of their
> history (like, bringing analysis "to the sides" of treeish1 instead of
> keeping analysis in revisions in the history of treeish2 that have
> treeish1 as one of their ancestors.... which is definitely a valid
> case for analysis, anyway). In this case, blame --reverse stops being
> helpful.
>
At the cost of being slower, I just pushed to master the best results yet.
The workaround I developed for the case I described on the previous
mail ended up providing much better results overall so I ended up
replacing the whole merge-analysis logic with it.
Thanks for your kind help and comments, Peff. Let me know how it goes.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox