* [PATCH v2 12/16] refs.c: make get_main_ref_store() public and use it
From: Nguyễn Thái Ngọc Duy @ 2017-02-16 11:48 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: <20170216114818.6080-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 55a80a83d..25f657a6f 100644
--- a/refs.c
+++ b/refs.c
@@ -1303,7 +1303,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);
}
@@ -1311,7 +1311,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);
}
@@ -1434,7 +1434,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;
@@ -1483,14 +1483,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);
}
@@ -1498,7 +1498,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);
@@ -1507,7 +1507,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);
}
@@ -1517,14 +1517,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);
@@ -1535,7 +1535,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);
@@ -1544,14 +1544,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);
}
@@ -1559,14 +1559,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);
}
@@ -1578,7 +1578,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,
@@ -1588,21 +1588,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 694784391..f803528fc 100644
--- a/refs.h
+++ b/refs.h
@@ -553,4 +553,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 v2 13/16] path.c: move some code out of strbuf_git_path_submodule()
From: Nguyễn Thái Ngọc Duy @ 2017-02-16 11:48 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: <20170216114818.6080-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 ece17315d..3ce589d55 100644
--- a/submodule.c
+++ b/submodule.c
@@ -1335,3 +1335,34 @@ void prepare_submodule_repo_env(struct argv_array *out)
}
argv_array_push(out, "GIT_DIR=.git");
}
+
+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 23d76682b..2728494ce 100644
--- a/submodule.h
+++ b/submodule.h
@@ -70,6 +70,7 @@ extern int push_unpushed_submodules(struct sha1_array *commits,
int dry_run);
void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir);
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 v2 14/16] refs: move submodule code out of files-backend.c
From: Nguyễn Thái Ngọc Duy @ 2017-02-16 11:48 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: <20170216114818.6080-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 | 26 ++++++++------------------
refs/refs-internal.h | 6 +++---
3 files changed, 24 insertions(+), 26 deletions(-)
diff --git a/refs.c b/refs.c
index 25f657a6f..58ac9a2a8 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
@@ -1419,9 +1420,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);
@@ -1430,7 +1431,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;
}
@@ -1455,6 +1456,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();
@@ -1465,8 +1467,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 74e31d041..e8946e638 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,12 +938,9 @@ 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 (is_per_worktree_ref(tmp.buf) ||
- (skip_prefix(tmp.buf, "logs/", &ref) &&
- is_per_worktree_ref(ref)))
+ if (is_per_worktree_ref(tmp.buf) ||
+ (skip_prefix(tmp.buf, "logs/", &ref) &&
+ is_per_worktree_ref(ref)))
strbuf_addf(sb, "%s/%s", refs->gitdir.buf, tmp.buf);
else
strbuf_addf(sb, "%s/%s", refs->gitcommondir.buf, tmp.buf);
@@ -1005,7 +995,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;
@@ -1015,8 +1005,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());
@@ -1032,8 +1023,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 69d02b6ba..d7112770d 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -476,12 +476,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 v2 15/16] files-backend: remove submodule_allowed from files_downcast()
From: Nguyễn Thái Ngọc Duy @ 2017-02-16 11:48 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: <20170216114818.6080-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 e8946e638..d9fc29d8d 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1017,24 +1017,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;
@@ -1044,9 +1033,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;
}
@@ -1382,7 +1368,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;
@@ -1575,7 +1561,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;
@@ -1799,7 +1784,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];
@@ -1908,7 +1893,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;
@@ -2041,7 +2026,6 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs,
int attempts_remaining = 3;
int resolved;
- files_assert_main_repository(refs, "lock_ref_sha1_basic");
assert(err);
lock = xcalloc(1, sizeof(struct ref_lock));
@@ -2189,8 +2173,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;
@@ -2230,8 +2212,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");
@@ -2263,8 +2243,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);
@@ -2410,7 +2388,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));
@@ -2443,7 +2421,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 */
@@ -2511,7 +2488,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;
@@ -2619,7 +2596,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);
@@ -2644,7 +2621,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;
@@ -2866,7 +2843,7 @@ static int files_create_reflog(struct ref_store *ref_store,
int ret;
struct strbuf sb = STRBUF_INIT;
struct files_ref_store *refs =
- files_downcast(ref_store, 0, "create_reflog");
+ files_downcast(ref_store, "create_reflog");
ret = log_ref_setup(refs, refname, &sb, err, force_create);
strbuf_release(&sb);
@@ -3004,8 +2981,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 (log_ref_write(refs, lock->ref_name, lock->old_oid.hash,
sha1, logmsg, 0, err)) {
@@ -3114,7 +3089,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;
@@ -3140,7 +3115,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;
@@ -3178,7 +3153,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;
@@ -3193,7 +3168,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;
@@ -3248,7 +3223,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;
@@ -3356,7 +3331,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;
@@ -3444,7 +3419,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;
@@ -3656,8 +3631,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;
@@ -3782,7 +3755,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;
@@ -3956,7 +3929,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;
@@ -4078,7 +4051,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;
@@ -4183,8 +4156,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 v2 16/16] refs: rename get_ref_store() to get_submodule_ref_store() and make it public
From: Nguyễn Thái Ngọc Duy @ 2017-02-16 11:48 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: <20170216114818.6080-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 58ac9a2a8..e7206a420 100644
--- a/refs.c
+++ b/refs.c
@@ -1160,7 +1160,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)
@@ -1333,10 +1333,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)
@@ -1452,13 +1452,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 f803528fc..1287ba59c 100644
--- a/refs.h
+++ b/refs.h
@@ -554,5 +554,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 d9fc29d8d..685ea5c14 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -3115,7 +3115,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 d7112770d..cb6882779 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -634,18 +634,6 @@ struct ref_store {
void base_ref_store_init(struct ref_store *refs,
const struct ref_storage_be *be);
-/*
- * Return the ref_store instance for the specified submodule. For the
- * main repository, use submodule==NULL; such a call cannot fail. For
- * a submodule, the submodule must exist and be a nonbare repository,
- * otherwise return NULL. If the requested reference store has not yet
- * been initialized, initialize it first.
- *
- * For backwards compatibility, submodule=="" is treated the same as
- * submodule==NULL.
- */
-struct ref_store *get_ref_store(const char *submodule);
-
const char *resolve_ref_recursively(struct ref_store *refs,
const char *refname,
int resolve_flags,
--
2.11.0.157.gd943d85
^ permalink raw reply related
* [PATCH v2 0/5] Kill manual ref parsing code in worktree.c
From: Nguyễn Thái Ngọc Duy @ 2017-02-16 12:02 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Michael Haggerty, Stefan Beller,
Nguyễn Thái Ngọc Duy
In-Reply-To: <20170208113144.8201-1-pclouds@gmail.com>
v2 still kills parse_ref(), but the series now depends on my other
series [1] and as a result does not make any confusing "submodule"
calls any more.
It also kills another function, introduced for multi-worktree, that
should not have been there to begin with. Good riddance.
Again, the naming convention with refs_ prefix for new APIs may not be
the best idea...
[1] public-inbox.org/git/20170213152011.12050-1-pclouds@gmail.com
Nguyễn Thái Ngọc Duy (5):
refs: introduce get_worktree_ref_store()
refs.c: add refs_resolve_ref_unsafe()
worktree.c: kill parse_ref() in favor of refs_resolve_ref_unsafe()
refs: add refs_create_symref()
refs: kill set_worktree_head_symref()
branch.c | 15 ++++----
refs.c | 58 ++++++++++++++++++++++++-----
refs.h | 21 ++++++-----
refs/files-backend.c | 43 +---------------------
refs/refs-internal.h | 5 ---
worktree.c | 102 ++++++++++++++-------------------------------------
worktree.h | 2 +-
7 files changed, 98 insertions(+), 148 deletions(-)
--
2.11.0.157.gd943d85
^ permalink raw reply
* [PATCH v2 1/5] refs: introduce get_worktree_ref_store()
From: Nguyễn Thái Ngọc Duy @ 2017-02-16 12:02 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Michael Haggerty, Stefan Beller,
Nguyễn Thái Ngọc Duy
In-Reply-To: <20170216120302.5302-1-pclouds@gmail.com>
files-backend at this point is still aware of the per-repo/worktree
separation in refs, so it can handle a linked worktree.
Note: accessing a worktree of a submodule remains unaddressed. Perhaps
after get_worktrees() can access submodule (or rather a new function
get_submodule_worktrees(), that lists worktrees of a submodule), we can
update this function to work with submodules as well.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
refs.c | 27 +++++++++++++++++++++++++++
refs.h | 2 ++
2 files changed, 29 insertions(+)
diff --git a/refs.c b/refs.c
index e7206a420..ba4d9420c 100644
--- a/refs.c
+++ b/refs.c
@@ -10,6 +10,7 @@
#include "object.h"
#include "tag.h"
#include "submodule.h"
+#include "worktree.h"
/*
* List of all available backends
@@ -1486,6 +1487,32 @@ struct ref_store *get_submodule_ref_store(const char *submodule)
return refs;
}
+struct ref_store *get_worktree_ref_store(const struct worktree *wt)
+{
+ struct ref_store *refs;
+
+ if (wt->is_current)
+ return get_main_ref_store();
+
+ /*
+ * We share the same hash map with submodules for
+ * now. submodule paths are always relative (to topdir) while
+ * worktree paths are always absolute. No chance of conflict.
+ */
+ refs = lookup_submodule_ref_store(wt->path);
+ if (refs)
+ return refs;
+
+ if (wt->id)
+ refs = ref_store_init(git_common_path("worktrees/%s", wt->id));
+ else
+ refs = ref_store_init(get_git_common_dir());
+
+ if (refs)
+ register_submodule_ref_store(refs, wt->path);
+ return refs;
+}
+
void base_ref_store_init(struct ref_store *refs,
const struct ref_storage_be *be)
{
diff --git a/refs.h b/refs.h
index 1287ba59c..464cc384a 100644
--- a/refs.h
+++ b/refs.h
@@ -565,5 +565,7 @@ struct ref_store *get_main_ref_store(void);
* submodule==NULL.
*/
struct ref_store *get_submodule_ref_store(const char *submodule);
+struct worktree;
+struct ref_store *get_worktree_ref_store(const struct worktree *wt);
#endif /* REFS_H */
--
2.11.0.157.gd943d85
^ permalink raw reply related
* [PATCH v2 2/5] refs.c: add refs_resolve_ref_unsafe()
From: Nguyễn Thái Ngọc Duy @ 2017-02-16 12:02 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Michael Haggerty, Stefan Beller,
Nguyễn Thái Ngọc Duy
In-Reply-To: <20170216120302.5302-1-pclouds@gmail.com>
Surprise surprise. This is just rename and introduce
resolve_ref_recursively() to the public.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
refs.c | 9 +++++----
refs.h | 6 ++++++
refs/files-backend.c | 2 +-
refs/refs-internal.h | 5 -----
4 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/refs.c b/refs.c
index ba4d9420c..e0e191107 100644
--- a/refs.c
+++ b/refs.c
@@ -1226,7 +1226,7 @@ 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_recursively(struct ref_store *refs,
+const char *refs_resolve_ref_unsafe(struct ref_store *refs,
const char *refname,
int resolve_flags,
unsigned char *sha1, int *flags)
@@ -1313,8 +1313,9 @@ int refs_init_db(struct strbuf *err)
const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
unsigned char *sha1, int *flags)
{
- return resolve_ref_recursively(get_main_ref_store(), refname,
- resolve_flags, sha1, flags);
+ return refs_resolve_ref_unsafe(get_main_ref_store(),
+ refname, resolve_flags,
+ sha1, flags);
}
int resolve_gitlink_ref(const char *submodule, const char *refname,
@@ -1343,7 +1344,7 @@ int resolve_gitlink_ref(const char *submodule, const char *refname,
if (!refs)
return -1;
- if (!resolve_ref_recursively(refs, refname, 0, sha1, &flags) ||
+ if (!refs_resolve_ref_unsafe(refs, refname, 0, sha1, &flags) ||
is_null_sha1(sha1))
return -1;
return 0;
diff --git a/refs.h b/refs.h
index 464cc384a..10c2cfc00 100644
--- a/refs.h
+++ b/refs.h
@@ -568,4 +568,10 @@ struct ref_store *get_submodule_ref_store(const char *submodule);
struct worktree;
struct ref_store *get_worktree_ref_store(const struct worktree *wt);
+const char *refs_resolve_ref_unsafe(struct ref_store *refs,
+ const char *refname,
+ int resolve_flags,
+ unsigned char *sha1,
+ int *flags);
+
#endif /* REFS_H */
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 685ea5c14..f3be620ab 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1276,7 +1276,7 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir)
create_dir_entry(refs, refname.buf,
refname.len, 1));
} else {
- if (!resolve_ref_recursively(&refs->base,
+ if (!refs_resolve_ref_unsafe(&refs->base,
refname.buf,
RESOLVE_REF_READING,
sha1, &flag)) {
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index cb6882779..6b29dc3b1 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -634,11 +634,6 @@ struct ref_store {
void base_ref_store_init(struct ref_store *refs,
const struct ref_storage_be *be);
-const char *resolve_ref_recursively(struct ref_store *refs,
- const char *refname,
- int resolve_flags,
- unsigned char *sha1, int *flags);
-
static inline int is_per_worktree_ref(const char *refname)
{
return !starts_with(refname, "refs/") ||
--
2.11.0.157.gd943d85
^ permalink raw reply related
* [PATCH v2 3/5] worktree.c: kill parse_ref() in favor of refs_resolve_ref_unsafe()
From: Nguyễn Thái Ngọc Duy @ 2017-02-16 12:03 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Michael Haggerty, Stefan Beller,
Nguyễn Thái Ngọc Duy
In-Reply-To: <20170216120302.5302-1-pclouds@gmail.com>
The manual parsing code is replaced with a call to refs_resolve_ref_unsafe().
The manual parsing code must die because only refs/files-backend.c
should do that.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
branch.c | 3 +-
worktree.c | 102 ++++++++++++++++---------------------------------------------
worktree.h | 2 +-
3 files changed, 30 insertions(+), 77 deletions(-)
diff --git a/branch.c b/branch.c
index c431cbf6a..fcb4a765c 100644
--- a/branch.c
+++ b/branch.c
@@ -354,7 +354,8 @@ int replace_each_worktree_head_symref(const char *oldref, const char *newref)
for (i = 0; worktrees[i]; i++) {
if (worktrees[i]->is_detached)
continue;
- if (strcmp(oldref, worktrees[i]->head_ref))
+ if (worktrees[i]->head_ref &&
+ strcmp(oldref, worktrees[i]->head_ref))
continue;
if (set_worktree_head_symref(get_worktree_git_dir(worktrees[i]),
diff --git a/worktree.c b/worktree.c
index eb6121263..f8f520036 100644
--- a/worktree.c
+++ b/worktree.c
@@ -19,54 +19,25 @@ void free_worktrees(struct worktree **worktrees)
free (worktrees);
}
-/*
- * read 'path_to_ref' into 'ref'. Also if is_detached is not NULL,
- * set is_detached to 1 (0) if the ref is detached (is not detached).
- *
- * $GIT_COMMON_DIR/$symref (e.g. HEAD) is practically outside $GIT_DIR so
- * for linked worktrees, `resolve_ref_unsafe()` won't work (it uses
- * git_path). Parse the ref ourselves.
- *
- * return -1 if the ref is not a proper ref, 0 otherwise (success)
- */
-static int parse_ref(char *path_to_ref, struct strbuf *ref, int *is_detached)
-{
- if (is_detached)
- *is_detached = 0;
- if (!strbuf_readlink(ref, path_to_ref, 0)) {
- /* HEAD is symbolic link */
- if (!starts_with(ref->buf, "refs/") ||
- check_refname_format(ref->buf, 0))
- return -1;
- } else if (strbuf_read_file(ref, path_to_ref, 0) >= 0) {
- /* textual symref or detached */
- if (!starts_with(ref->buf, "ref:")) {
- if (is_detached)
- *is_detached = 1;
- } else {
- strbuf_remove(ref, 0, strlen("ref:"));
- strbuf_trim(ref);
- if (check_refname_format(ref->buf, 0))
- return -1;
- }
- } else
- return -1;
- return 0;
-}
-
/**
- * Add the head_sha1 and head_ref (if not detached) to the given worktree
+ * Update head_sha1, head_ref and is_detached of the given worktree
*/
-static void add_head_info(struct strbuf *head_ref, struct worktree *worktree)
+static void add_head_info(struct worktree *wt)
{
- if (head_ref->len) {
- if (worktree->is_detached) {
- get_sha1_hex(head_ref->buf, worktree->head_sha1);
- } else {
- resolve_ref_unsafe(head_ref->buf, 0, worktree->head_sha1, NULL);
- worktree->head_ref = strbuf_detach(head_ref, NULL);
- }
- }
+ int flags;
+ const char *target;
+
+ target = refs_resolve_ref_unsafe(get_worktree_ref_store(wt),
+ "HEAD",
+ RESOLVE_REF_READING,
+ wt->head_sha1, &flags);
+ if (!target)
+ return;
+
+ if (flags & REF_ISSYMREF)
+ wt->head_ref = xstrdup(target);
+ else
+ wt->is_detached = 1;
}
/**
@@ -77,9 +48,7 @@ static struct worktree *get_main_worktree(void)
struct worktree *worktree = NULL;
struct strbuf path = STRBUF_INIT;
struct strbuf worktree_path = STRBUF_INIT;
- struct strbuf head_ref = STRBUF_INIT;
int is_bare = 0;
- int is_detached = 0;
strbuf_add_absolute_path(&worktree_path, get_git_common_dir());
is_bare = !strbuf_strip_suffix(&worktree_path, "/.git");
@@ -91,13 +60,10 @@ static struct worktree *get_main_worktree(void)
worktree = xcalloc(1, sizeof(*worktree));
worktree->path = strbuf_detach(&worktree_path, NULL);
worktree->is_bare = is_bare;
- worktree->is_detached = is_detached;
- if (!parse_ref(path.buf, &head_ref, &is_detached))
- add_head_info(&head_ref, worktree);
+ add_head_info(worktree);
strbuf_release(&path);
strbuf_release(&worktree_path);
- strbuf_release(&head_ref);
return worktree;
}
@@ -106,8 +72,6 @@ static struct worktree *get_linked_worktree(const char *id)
struct worktree *worktree = NULL;
struct strbuf path = STRBUF_INIT;
struct strbuf worktree_path = STRBUF_INIT;
- struct strbuf head_ref = STRBUF_INIT;
- int is_detached = 0;
if (!id)
die("Missing linked worktree name");
@@ -127,19 +91,14 @@ static struct worktree *get_linked_worktree(const char *id)
strbuf_reset(&path);
strbuf_addf(&path, "%s/worktrees/%s/HEAD", get_git_common_dir(), id);
- if (parse_ref(path.buf, &head_ref, &is_detached) < 0)
- goto done;
-
worktree = xcalloc(1, sizeof(*worktree));
worktree->path = strbuf_detach(&worktree_path, NULL);
worktree->id = xstrdup(id);
- worktree->is_detached = is_detached;
- add_head_info(&head_ref, worktree);
+ add_head_info(worktree);
done:
strbuf_release(&path);
strbuf_release(&worktree_path);
- strbuf_release(&head_ref);
return worktree;
}
@@ -334,8 +293,6 @@ const struct worktree *find_shared_symref(const char *symref,
const char *target)
{
const struct worktree *existing = NULL;
- struct strbuf path = STRBUF_INIT;
- struct strbuf sb = STRBUF_INIT;
static struct worktree **worktrees;
int i = 0;
@@ -345,6 +302,11 @@ const struct worktree *find_shared_symref(const char *symref,
for (i = 0; worktrees[i]; i++) {
struct worktree *wt = worktrees[i];
+ const char *symref_target;
+ unsigned char sha1[20];
+ struct ref_store *refs;
+ int flags;
+
if (wt->is_bare)
continue;
@@ -359,24 +321,14 @@ const struct worktree *find_shared_symref(const char *symref,
}
}
- strbuf_reset(&path);
- strbuf_reset(&sb);
- strbuf_addf(&path, "%s/%s",
- get_worktree_git_dir(wt),
- symref);
-
- if (parse_ref(path.buf, &sb, NULL)) {
- continue;
- }
-
- if (!strcmp(sb.buf, target)) {
+ refs = get_worktree_ref_store(wt);
+ symref_target = refs_resolve_ref_unsafe(refs, symref, 0,
+ sha1, &flags);
+ if ((flags & REF_ISSYMREF) && !strcmp(symref_target, target)) {
existing = wt;
break;
}
}
- strbuf_release(&path);
- strbuf_release(&sb);
-
return existing;
}
diff --git a/worktree.h b/worktree.h
index d59ce1fee..961252e71 100644
--- a/worktree.h
+++ b/worktree.h
@@ -4,7 +4,7 @@
struct worktree {
char *path;
char *id;
- char *head_ref;
+ char *head_ref; /* NULL if HEAD is broken or detached */
char *lock_reason; /* internal use */
unsigned char head_sha1[20];
int is_detached;
--
2.11.0.157.gd943d85
^ permalink raw reply related
* [PATCH v2 4/5] refs: add refs_create_symref()
From: Nguyễn Thái Ngọc Duy @ 2017-02-16 12:03 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Michael Haggerty, Stefan Beller,
Nguyễn Thái Ngọc Duy
In-Reply-To: <20170216120302.5302-1-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
refs.c | 22 +++++++++++++++++-----
refs.h | 4 ++++
2 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/refs.c b/refs.c
index e0e191107..23e0a8eda 100644
--- a/refs.c
+++ b/refs.c
@@ -1535,13 +1535,25 @@ int peel_ref(const char *refname, unsigned char *sha1)
return refs->be->peel_ref(refs, refname, sha1);
}
-int create_symref(const char *ref_target, const char *refs_heads_master,
+int refs_create_symref(struct ref_store *refs,
+ const char *ref_target,
+ const char *refs_heads_master,
+ const char *logmsg)
+{
+ return refs->be->create_symref(refs,
+ ref_target,
+ refs_heads_master,
+ logmsg);
+}
+
+int create_symref(const char *ref_target,
+ const char *refs_heads_master,
const char *logmsg)
{
- struct ref_store *refs = get_main_ref_store();
-
- return refs->be->create_symref(refs, ref_target, refs_heads_master,
- logmsg);
+ return refs_create_symref(get_main_ref_store(),
+ ref_target,
+ refs_heads_master,
+ logmsg);
}
int ref_transaction_commit(struct ref_transaction *transaction,
diff --git a/refs.h b/refs.h
index 10c2cfc00..694769963 100644
--- a/refs.h
+++ b/refs.h
@@ -573,5 +573,9 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
int resolve_flags,
unsigned char *sha1,
int *flags);
+int refs_create_symref(struct ref_store *refs,
+ const char *refname,
+ const char *target,
+ const char *logmsg);
#endif /* REFS_H */
--
2.11.0.157.gd943d85
^ permalink raw reply related
* [PATCH v2 5/5] refs: kill set_worktree_head_symref()
From: Nguyễn Thái Ngọc Duy @ 2017-02-16 12:03 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Michael Haggerty, Stefan Beller,
Nguyễn Thái Ngọc Duy
In-Reply-To: <20170216120302.5302-1-pclouds@gmail.com>
70999e9cec (branch -m: update all per-worktree HEADs - 2016-03-27)
added this function in order to update HEADs of all relevant
worktrees, when a branch is renamed.
It, as a public ref api, kind of breaks abstraction when it uses
internal functions of files backend. With the introduction of
refs_create_symref(), we can move back pretty close to the code before
70999e9cec, where create_symref() was used for updating HEAD.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
branch.c | 12 ++++++------
refs.h | 9 ---------
refs/files-backend.c | 41 -----------------------------------------
3 files changed, 6 insertions(+), 56 deletions(-)
diff --git a/branch.c b/branch.c
index fcb4a765c..ad0cc0489 100644
--- a/branch.c
+++ b/branch.c
@@ -352,18 +352,18 @@ int replace_each_worktree_head_symref(const char *oldref, const char *newref)
int i;
for (i = 0; worktrees[i]; i++) {
+ struct ref_store *refs;
+
if (worktrees[i]->is_detached)
continue;
if (worktrees[i]->head_ref &&
strcmp(oldref, worktrees[i]->head_ref))
continue;
- if (set_worktree_head_symref(get_worktree_git_dir(worktrees[i]),
- newref)) {
- ret = -1;
- error(_("HEAD of working tree %s is not updated"),
- worktrees[i]->path);
- }
+ refs = get_worktree_ref_store(worktrees[i]);
+ if (refs_create_symref(refs, "HEAD", newref, NULL))
+ ret = error(_("HEAD of working tree %s is not updated"),
+ worktrees[i]->path);
}
free_worktrees(worktrees);
diff --git a/refs.h b/refs.h
index 694769963..bce77891a 100644
--- a/refs.h
+++ b/refs.h
@@ -325,15 +325,6 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg);
int create_symref(const char *refname, const char *target, const char *logmsg);
-/*
- * Update HEAD of the specified gitdir.
- * Similar to create_symref("relative-git-dir/HEAD", target, NULL), but
- * this can update the main working tree's HEAD regardless of where
- * $GIT_DIR points to.
- * Return 0 if successful, non-zero otherwise.
- * */
-int set_worktree_head_symref(const char *gitdir, const char *target);
-
enum action_on_err {
UPDATE_REFS_MSG_ON_ERR,
UPDATE_REFS_DIE_ON_ERR,
diff --git a/refs/files-backend.c b/refs/files-backend.c
index f3be620ab..ba56e46d4 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -3108,47 +3108,6 @@ static int files_create_symref(struct ref_store *ref_store,
return ret;
}
-int set_worktree_head_symref(const char *gitdir, const char *target)
-{
- /*
- * FIXME: this obviously will not work well for future refs
- * backends. This function needs to die.
- */
- struct files_ref_store *refs =
- 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;
- const char *head_rel;
- int ret;
-
- strbuf_addf(&head_path, "%s/HEAD", absolute_path(gitdir));
- if (hold_lock_file_for_update(&head_lock, head_path.buf,
- LOCK_NO_DEREF) < 0) {
- struct strbuf err = STRBUF_INIT;
- unable_to_lock_message(head_path.buf, errno, &err);
- error("%s", err.buf);
- strbuf_release(&err);
- strbuf_release(&head_path);
- return -1;
- }
-
- /* head_rel will be "HEAD" for the main tree, "worktrees/wt/HEAD" for
- linked trees */
- head_rel = remove_leading_path(head_path.buf,
- absolute_path(get_git_common_dir()));
- /* to make use of create_symref_locked(), initialize ref_lock */
- lock = xcalloc(1, sizeof(struct ref_lock));
- lock->lk = &head_lock;
- lock->ref_name = xstrdup(head_rel);
-
- ret = create_symref_locked(refs, lock, head_rel, target, NULL);
-
- unlock_ref(lock); /* will free lock */
- strbuf_release(&head_path);
- return ret;
-}
-
static int files_reflog_exists(struct ref_store *ref_store,
const char *refname)
{
--
2.11.0.157.gd943d85
^ permalink raw reply related
* Re: [PATCH] show-branch: fix crash with long ref name
From: Christian Couder @ 2017-02-16 12:40 UTC (permalink / raw)
To: Jeff King; +Cc: Junio C Hamano, git, Maxim Kuvyrkov, Pranit Bauva
In-Reply-To: <20170215214052.5py4pxkcz4g2bmtk@sigill.intra.peff.net>
On Wed, Feb 15, 2017 at 10:40 PM, Jeff King <peff@peff.net> wrote:
> On Tue, Feb 14, 2017 at 10:29:46PM +0100, Christian Couder wrote:
>
>> > I notice Christian's patch added a few tests. I don't know if we'd want
>> > to squash them in (I didn't mean to override his patch at all; I was
>> > about to send mine out when I noticed his, and I wondered if we wanted
>> > to combine the two efforts).
>>
>> I think it would be nice to have at least one test. Feel free to
>> squash mine if you want.
>
> I started to add some tests, but I had second thoughts. It _is_ nice
> to show off the fix, but as far as regressions go, this specific case is
> unlikely to come up again. What would be more valuable, I think, is a
> test script which set up a very long refname (not just 150 bytes or
> whatever) and ran it through a series of git commands.
I agree that a test script running through a series of command with
long refnames would be great.
But I think the refname should not necesarily be too long. As I wrote
in the commit message of my patch, if the ref name had been much
longer the crash would not have happened because the ref could not
have been created in the first place.
So the best would be to run through a series of commands with a
refname ranging from let's say 80 chars to 300 chars.
That would have a chance to catch crashes due to legacy code using for
example things like `char stuff[128]` or `char stuff[256]`.
Implementing those tests could have started with something like the
test case I sent, but as it would in the end be about many different
commands, one can see it as part of a different topic.
> But then you run into all sorts of portability annoyances with pathname
> restrictions (you can hack around creation by writing the refname
> directly into packed-refs, but most manipulations will want to take the
> .lock in the filesystem).
Yeah, but if a crash doesn't happen because we die() as the ref is too
long for the file system, we could detect that and make the test
succeed.
> So I dunno. It seems like being thorough is a
> lot of hassle for not much gain. Being not-thorough is easy, but is
> mostly a token that is unlikely to find any real bugs.
Yeah, if we really care, it might be better to start using a fuzzer or
a property based testing tool instead of bothering with these kind of
tests by ourselves, which is also a different topic.
> So I punted, at least for now.
Ok, no problem.
^ permalink raw reply
* [PATCH 0/4 v4] WIP: allow "-" as a shorthand for "previous branch"
From: Siddharth Kannan @ 2017-02-16 15:14 UTC (permalink / raw)
To: git
Cc: gitster, Matthieu.Moy, pranit.bauva, peff, pclouds, sandals,
Siddharth Kannan
This is as per our discussion[1]. The patches and commit messages are based on
Junio's patches that were posted as a reply to
<20170212184132.12375-1-gitster@pobox.com>.
As per Matthieu's comments, I have updated the tests, but there is still one
thing that is not working: log -@{yesterday} or log -@{2.days.ago}
For the other kinds of suffixes, such as -^ or -~ or -~N, the suffix
information is first extracted and then, the function get_sha1_1 is called with
name="-^" and len=1 (which is the reason for the changed condition inside Patch
4 of this series).
For -@{yesterday} kind of queries, the functions dwim_log,
interpret_branch_name and interpret_nth_prior_checkout are called.
1. A nice way to solve this would be to extend the replacement of "-" with
"@{-1}" one step further. Using strbuf, instead of replacing the whole string
with "@{-1}" we would simply replace "-" with "@{-1}" expanding the string
appropriately. This will ensure that all the code is inside the function
get_sha1_1. The code to do this is in the cover section of the 4th patch in this
series.
2. we could go down the dwim_log codepath, and find another suitable place to
make the same "-" -> "@{-1}" replacement. In the time that I spent till now, it
seems that the suffix information (i.e. @{yesterday} or @{2.days.ago}) is
extracted _after_ the branch information has been extracted, so I suspect that
we will have to keep that part intact even in this solution. (I am not too
sure about this. If this is the preferred solution, then I will dig deeper and
find the right place as I did for the first part of this patch)
Matthieu: Thanks a lot for your comments on the tests! test_commit has made the
tests a lot cleaner!
[1]: <xmqqh941ippo.fsf@gitster.mtv.corp.google.com>
Siddharth Kannan (4):
revision.c: do not update argv with unknown option
revision.c: swap if/else blocks
revision.c: args starting with "-" might be a revision
sha1_name.c: teach get_sha1_1 "-" shorthand for "@{-1}"
revision.c | 15 ++++---
sha1_name.c | 5 +++
t/t4214-log-shorthand.sh | 106 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 120 insertions(+), 6 deletions(-)
create mode 100755 t/t4214-log-shorthand.sh
--
2.1.4
^ permalink raw reply
* [PATCH 1/4 v4] revision.c: do not update argv with unknown option
From: Siddharth Kannan @ 2017-02-16 15:14 UTC (permalink / raw)
To: git
Cc: gitster, Matthieu.Moy, pranit.bauva, peff, pclouds, sandals,
Siddharth Kannan
In-Reply-To: <1487258054-32292-1-git-send-email-kannan.siddharth12@gmail.com>
handle_revision_opt() tries to recognize and handle the given argument. If an
option was unknown to it, it used to add the option to unkv[(*unkc)++]. This
increment of unkc causes the variable in the caller to change.
Teach handle_revision_opt to not update unknown arguments inside unkc anymore.
This is now the responsibility of the caller.
There are two callers of this function:
1. setup_revision: Changes have been made so that setup_revision will now
update the unknown option in argv
2. parse_revision_opt: No changes are required here. This function throws an
error whenever the option provided as argument was unknown to
handle_revision_opt().
Signed-off-by: Siddharth Kannan <kannan.siddharth12@gmail.com>
---
revision.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/revision.c b/revision.c
index b37dbec..5674a9a 100644
--- a/revision.c
+++ b/revision.c
@@ -2016,8 +2016,6 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
revs->ignore_missing = 1;
} else {
int opts = diff_opt_parse(&revs->diffopt, argv, argc, revs->prefix);
- if (!opts)
- unkv[(*unkc)++] = arg;
return opts;
}
if (revs->graph && revs->track_linear)
@@ -2234,6 +2232,8 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
}
if (opts < 0)
exit(128);
+ /* arg is an unknown option */
+ argv[left++] = arg;
continue;
}
--
2.1.4
^ permalink raw reply related
* [PATCH 2/4 v4] revision.c: swap if/else blocks
From: Siddharth Kannan @ 2017-02-16 15:14 UTC (permalink / raw)
To: git
Cc: gitster, Matthieu.Moy, pranit.bauva, peff, pclouds, sandals,
Siddharth Kannan
In-Reply-To: <1487258054-32292-1-git-send-email-kannan.siddharth12@gmail.com>
Swap the condition and bodies of an "if (A) do_A else do_B" in
setup_revisions() to "if (!A) do_B else do_A", to make the change in
the the next step easier to read.
No behaviour change is intended in this step.
Signed-off-by: Siddharth Kannan <kannan.siddharth12@gmail.com>
---
revision.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/revision.c b/revision.c
index 5674a9a..8d4ddae 100644
--- a/revision.c
+++ b/revision.c
@@ -2238,7 +2238,9 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
}
- if (handle_revision_arg(arg, revs, flags, revarg_opt)) {
+ if (!handle_revision_arg(arg, revs, flags, revarg_opt))
+ got_rev_arg = 1;
+ else {
int j;
if (seen_dashdash || *arg == '^')
die("bad revision '%s'", arg);
@@ -2255,8 +2257,6 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
append_prune_data(&prune_data, argv + i);
break;
}
- else
- got_rev_arg = 1;
}
if (prune_data.nr) {
--
2.1.4
^ permalink raw reply related
* [PATCH 3/4 v4] revision.c: args starting with "-" might be a revision
From: Siddharth Kannan @ 2017-02-16 15:14 UTC (permalink / raw)
To: git
Cc: gitster, Matthieu.Moy, pranit.bauva, peff, pclouds, sandals,
Siddharth Kannan
In-Reply-To: <1487258054-32292-1-git-send-email-kannan.siddharth12@gmail.com>
setup_revisions used to consider any argument starting with "-" to be either a
valid or an unknown option.
Teach setup_revisions to check if an argument is a revision before adding it as
an unknown option (something that setup_revisions didn't understand) to argv,
and moving on to the next argument.
This patch prepares the addition of "-" as a shorthand for "previous branch".
Signed-off-by: Siddharth Kannan <kannan.siddharth12@gmail.com>
---
revision.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/revision.c b/revision.c
index 8d4ddae..5470c33 100644
--- a/revision.c
+++ b/revision.c
@@ -2203,6 +2203,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
read_from_stdin = 0;
for (left = i = 1; i < argc; i++) {
const char *arg = argv[i];
+ int maybe_opt = 0;
if (*arg == '-') {
int opts;
@@ -2232,15 +2233,17 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
}
if (opts < 0)
exit(128);
- /* arg is an unknown option */
- argv[left++] = arg;
- continue;
+ maybe_opt = 1;
}
if (!handle_revision_arg(arg, revs, flags, revarg_opt))
got_rev_arg = 1;
- else {
+ else if (maybe_opt) {
+ /* arg is an unknown option */
+ argv[left++] = arg;
+ continue;
+ } else {
int j;
if (seen_dashdash || *arg == '^')
die("bad revision '%s'", arg);
--
2.1.4
^ permalink raw reply related
* [PATCH 4/4 v4] sha1_name.c: teach get_sha1_1 "-" shorthand for "@{-1}"
From: Siddharth Kannan @ 2017-02-16 15:14 UTC (permalink / raw)
To: git
Cc: gitster, Matthieu.Moy, pranit.bauva, peff, pclouds, sandals,
Siddharth Kannan
In-Reply-To: <1487258054-32292-1-git-send-email-kannan.siddharth12@gmail.com>
This patch introduces "-" as a method to refer to a revision, and adds tests to
test that git-log works with this shorthand.
This change will touch the following commands (through
revision.c:setup_revisions):
* builtin/blame.c
* builtin/diff.c
* builtin/diff-files.c
* builtin/diff-index.c
* builtin/diff-tree.c
* builtin/log.c
* builtin/rev-list.c
* builtin/shortlog.c
* builtin/fast-export.c
* builtin/fmt-merge-msg.c
builtin/add.c
builtin/checkout.c
builtin/commit.c
builtin/merge.c
builtin/pack-objects.c
builtin/revert.c
* marked commands are information-only.
As most commands in this list are not of the rm-variety, (i.e a command that
would delete something), this change does not make it easier for people to
delete. (eg: "git branch -d -" is *not* enabled by this patch)
Signed-off-by: Siddharth Kannan <kannan.siddharth12@gmail.com>
---
Instead of replacing the whole string, we would expand it accordingly using:
if (*name == '-') {
if (len == 1) {
name = "@{-1}";
len = 5;
} else {
struct strbuf changed_argument = STRBUF_INIT;
strbuf_addstr(&changed_argument, "@{-1}");
strbuf_addstr(&changed_argument, name + 1);
strbuf_setlen(&changed_argument, strlen(name) + 4);
name = strbuf_detach(&changed_argument, NULL);
}
}
Junio's comments on a previous version of the patch which used this same
approach but inside setup_revisions [1]
[1]: <xmqqtw882n08.fsf@gitster.mtv.corp.google.com>
sha1_name.c | 5 +++
t/t4214-log-shorthand.sh | 106 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 111 insertions(+)
create mode 100755 t/t4214-log-shorthand.sh
diff --git a/sha1_name.c b/sha1_name.c
index 73a915f..2f86bc9 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -947,6 +947,11 @@ static int get_sha1_1(const char *name, int len, unsigned char *sha1, unsigned l
if (!ret)
return 0;
+ if (*name == '-' && len == 1) {
+ name = "@{-1}";
+ len = 5;
+ }
+
ret = get_sha1_basic(name, len, sha1, lookup_flags);
if (!ret)
return 0;
diff --git a/t/t4214-log-shorthand.sh b/t/t4214-log-shorthand.sh
new file mode 100755
index 0000000..659b100
--- /dev/null
+++ b/t/t4214-log-shorthand.sh
@@ -0,0 +1,106 @@
+#!/bin/sh
+
+test_description='log can show previous branch using shorthand - for @{-1}'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ test_commit first &&
+ test_commit second &&
+ test_commit third &&
+ test_commit fourth &&
+ test_commit fifth &&
+ test_commit sixth &&
+ test_commit seventh
+'
+
+test_expect_success '"log -" should not work initially' '
+ test_must_fail git log -
+'
+
+test_expect_success 'setup branches for testing' '
+ git checkout -b testing-1 master^ &&
+ git checkout -b testing-2 master~2 &&
+ git checkout master
+'
+
+test_expect_success '"log -" should work' '
+ git log testing-2 >expect &&
+ git log - >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'symmetric revision range should work when one end is left empty' '
+ git checkout testing-2 &&
+ git checkout master &&
+ git log ...@{-1} >expect.first_empty &&
+ git log @{-1}... >expect.last_empty &&
+ git log ...- >actual.first_empty &&
+ git log -... >actual.last_empty &&
+ test_cmp expect.first_empty actual.first_empty &&
+ test_cmp expect.last_empty actual.last_empty
+'
+
+test_expect_success 'asymmetric revision range should work when one end is left empty' '
+ git checkout testing-2 &&
+ git checkout master &&
+ git log ..@{-1} >expect.first_empty &&
+ git log @{-1}.. >expect.last_empty &&
+ git log ..- >actual.first_empty &&
+ git log -.. >actual.last_empty &&
+ test_cmp expect.first_empty actual.first_empty &&
+ test_cmp expect.last_empty actual.last_empty
+'
+
+test_expect_success 'symmetric revision range should work when both ends are given' '
+ git checkout testing-2 &&
+ git checkout master &&
+ git log -...testing-1 >expect &&
+ git log testing-2...testing-1 >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'asymmetric revision range should work when both ends are given' '
+ git checkout testing-2 &&
+ git checkout master &&
+ git log -..testing-1 >expect &&
+ git log testing-2..testing-1 >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'multiple separate arguments should be handled properly' '
+ git checkout testing-2 &&
+ git checkout master &&
+ git log - - >expect.1 &&
+ git log @{-1} @{-1} >actual.1 &&
+ git log - HEAD >expect.2 &&
+ git log @{-1} HEAD >actual.2 &&
+ test_cmp expect.1 actual.1 &&
+ test_cmp expect.2 actual.2
+'
+
+test_expect_success 'revision ranges with same start and end should be empty' '
+ git checkout testing-2 &&
+ git checkout master &&
+ test 0 -eq $(git log -...- | wc -l) &&
+ test 0 -eq $(git log -..- | wc -l)
+'
+
+test_expect_success 'suffixes to - should work' '
+ git checkout testing-2 &&
+ git checkout master &&
+ git log -~ >expect.1 &&
+ git log @{-1}~ >actual.1 &&
+ git log -~2 >expect.2 &&
+ git log @{-1}~2 >actual.2 &&
+ git log -^ >expect.3 &&
+ git log @{-1}^ >actual.3 &&
+ git log -@{yesterday} >expect.4 &&
+ git log @{-1}@{yesterday} >actual.4 &&
+ test_cmp expect.1 actual.1 &&
+ test_cmp expect.2 actual.2 &&
+ test_cmp expect.3 actual.3 &&
+ test_cmp expect.4 actual.4
+'
+
+test_done
--
2.1.4
^ permalink raw reply related
* Re: [PATCH 1/3] add git_psprintf helper function
From: Jonathan Tan @ 2017-02-16 15:51 UTC (permalink / raw)
To: Maxim Moseychuk, git; +Cc: peff
In-Reply-To: <20170216112829.18079-2-franchesko.salias.hudro.pedros@gmail.com>
On 02/16/2017 03:28 AM, Maxim Moseychuk wrote:
> There are a number of places in the code where we call
> xsnprintf(), with the assumption that the output will fit into
> the buffer. If the buffer is small, then git die.
> In many places buffers have compile-time size, but generated string
> depends from current system locale (gettext)and can have size
> greater the buffer.
> Just run "LANG=ru_RU.UTF8 git bisect start v4.9 v4.8"
> on linux sources - it impossible.
>
> git_psprintf is similar to the standard C sprintf() function
> but safer, since it calculates the maximum space required
> and allocates memory to hold the result.
> The returned string should be freed with free() when no longer needed.
If I understand this correctly, xstrfmt (in strbuf.h) should already do
what you need, so you do not need a new function.
^ permalink raw reply
* Re: [PATCH 0/4 v4] WIP: allow "-" as a shorthand for "previous branch"
From: Matthieu Moy @ 2017-02-16 16:41 UTC (permalink / raw)
To: Siddharth Kannan; +Cc: git, gitster, pranit.bauva, peff, pclouds, sandals
In-Reply-To: <1487258054-32292-1-git-send-email-kannan.siddharth12@gmail.com>
Siddharth Kannan <kannan.siddharth12@gmail.com> writes:
> This is as per our discussion[1]. The patches and commit messages are based on
> Junio's patches that were posted as a reply to
> <20170212184132.12375-1-gitster@pobox.com>.
>
> As per Matthieu's comments, I have updated the tests, but there is still one
> thing that is not working: log -@{yesterday} or log -@{2.days.ago}
Note that I did not request that these things work, just that they seem
to be relevant tests: IMHO it's OK to reject them, but for example we
don't want them to segfault. And having a test is a good hint that you
thought about what could happen and to document it.
--
Matthieu Moy
http://www-verimag.imag.fr/~moy/
^ permalink raw reply
* Re: Confusing git messages when disk is full.
From: Jeff King @ 2017-02-16 16:44 UTC (permalink / raw)
To: Andreas Schwab; +Cc: Junio C Hamano, Jáchym Barvínek, git
In-Reply-To: <87tw7uv439.fsf@linux-m68k.org>
On Thu, Feb 16, 2017 at 11:10:18AM +0100, Andreas Schwab wrote:
> >> int xfclose(FILE *fp)
> >> {
> >> return ferror(fp) | fclose(fp);
> >> }
> >
> > Yes, that's exactly what I had in mind (might be worth calling out the
> > bitwise-OR, though, just to make it clear it's not a typo).
>
> Since the order of evaluation is unspecified, it would be better to
> force sequencing ferror before fclose.
Good point. Arguably the call in tempfile.c is buggy.
-Peff
^ permalink raw reply
* Re: [PATCH 1/4 v4] revision.c: do not update argv with unknown option
From: Matthieu Moy @ 2017-02-16 16:48 UTC (permalink / raw)
To: Siddharth Kannan; +Cc: git, gitster, pranit.bauva, peff, pclouds, sandals
In-Reply-To: <1487258054-32292-2-git-send-email-kannan.siddharth12@gmail.com>
Siddharth Kannan <kannan.siddharth12@gmail.com> writes:
> handle_revision_opt() tries to recognize and handle the given argument. If an
> option was unknown to it, it used to add the option to unkv[(*unkc)++]. This
> increment of unkc causes the variable in the caller to change.
>
> Teach handle_revision_opt to not update unknown arguments inside unkc anymore.
> This is now the responsibility of the caller.
>
> There are two callers of this function:
>
> 1. setup_revision: Changes have been made so that setup_revision will now
> update the unknown option in argv
You're writting "Changes have been made", but I did not see any up to
this point in the series.
We write patch series so that they are bisectable, i.e. each commit
should be correct (compileable, pass tests, consistent
documentation, ...). Here, it seems you are introducing a breakage to
repair it later.
Other that bisectability, this makes review harder: at this point the
reader knows it's broken, guesses that it will be repaired later, but
does not know in which patch.
--
Matthieu Moy
http://www-verimag.imag.fr/~moy/
^ permalink raw reply
* Re: [PATCH] config: preserve <subsection> case for one-shot config on the command line
From: Junio C Hamano @ 2017-02-16 16:59 UTC (permalink / raw)
To: Lars Schneider; +Cc: Jonathan Tan, git, sbeller
In-Reply-To: <D0CDD1AC-05CA-47F3-8CB5-61EA1C6515A8@gmail.com>
Lars Schneider <larsxschneider@gmail.com> writes:
>> On 16 Feb 2017, at 00:48, Junio C Hamano <gitster@pobox.com> wrote:
>>
>> The "git -c <var>=<val> cmd" mechanism is to pretend that a
>
> The problem is also present for gitconfig variables e.g.
> git config --local submodule.UPPERSUB.update none
Yuck.
> But your patch below fixes that, too!
Heh.
> Should we add a test case to this patch?
> If not, do you want me to improve my test case patch [1]
> or do you want to ditch the test?
I think a new test for submodule (although it already exists thanks
t you) is a bit too roundabout way to demonstrate the breakage and
protect the fix.
We'd perhaps want some tests for "git config", probably.
In a repository with /etc/gitconfig and $HOME/ that are tightly
controlled (I think our test framework already do so), running these
would demonstrate both breakages, I would think, but I am sure
people can come up with other forms that are a lot easier to read..
$ git -c v.A.r=val -c v.a.r=ue config --get-all v.a.r
$ git -c v.A.r=val -c v.a.r=ue config --get-all v.A.r
$ git -c v.a.r=val -c v.A.r=ue config --get-all v.a.r
$ git -c v.a.r=val -c v.A.r=ue config --get-all v.A.r
Thanks.
^ permalink raw reply
* Re: [PATCH 1/3] add git_psprintf helper function
From: Jeff King @ 2017-02-16 17:03 UTC (permalink / raw)
To: Jonathan Tan; +Cc: Maxim Moseychuk, git
In-Reply-To: <616a2b08-71f9-d594-d46c-2687bf20ae2b@google.com>
On Thu, Feb 16, 2017 at 07:51:14AM -0800, Jonathan Tan wrote:
> On 02/16/2017 03:28 AM, Maxim Moseychuk wrote:
> > There are a number of places in the code where we call
> > xsnprintf(), with the assumption that the output will fit into
> > the buffer. If the buffer is small, then git die.
> > In many places buffers have compile-time size, but generated string
> > depends from current system locale (gettext)and can have size
> > greater the buffer.
> > Just run "LANG=ru_RU.UTF8 git bisect start v4.9 v4.8"
> > on linux sources - it impossible.
> >
> > git_psprintf is similar to the standard C sprintf() function
> > but safer, since it calculates the maximum space required
> > and allocates memory to hold the result.
> > The returned string should be freed with free() when no longer needed.
>
> If I understand this correctly, xstrfmt (in strbuf.h) should already do what
> you need, so you do not need a new function.
Yes, this is exactly what xstrfmt is for.
-Peff
^ permalink raw reply
* [PATCH V2 0/2] Fix l10n
From: Maxim Moseychuk @ 2017-02-16 17:07 UTC (permalink / raw)
To: git; +Cc: peff, jonathantanmy, Maxim Moseychuk
In some places static size buffers can't store formatted string.
If it be happen then git die.
Jonathan Tan: Thanks a lot for your help.
Maxim Moseychuk (2):
bisect_next_all: convert xsnprintf to xstrfmt
stop_progress_msg: convert xsnprintf to xstrfmt
bisect.c | 9 +++++----
progress.c | 9 +++------
2 files changed, 8 insertions(+), 10 deletions(-)
--
2.11.1
^ permalink raw reply
* [PATCH V2 1/2] bisect_next_all: convert xsnprintf to xstrfmt
From: Maxim Moseychuk @ 2017-02-16 17:07 UTC (permalink / raw)
To: git; +Cc: peff, jonathantanmy, Maxim Moseychuk
In-Reply-To: <20170216170713.10065-1-franchesko.salias.hudro.pedros@gmail.com>
Git can't run bisect between 2048+ commits if use russian translation.
Reproduce "LANG=ru_RU.UTF8 git bisect start v4.9 v4.8" on linux sources.
Dummy solution: just increase buffer size but is not safe.
Size gettext string is a runtime value.
Signed-off-by: Maxim Moseychuk <franchesko.salias.hudro.pedros@gmail.com>
---
bisect.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/bisect.c b/bisect.c
index 21bc6daa4..787543cad 100644
--- a/bisect.c
+++ b/bisect.c
@@ -940,7 +940,7 @@ int bisect_next_all(const char *prefix, int no_checkout)
struct commit_list *tried;
int reaches = 0, all = 0, nr, steps;
const unsigned char *bisect_rev;
- char steps_msg[32];
+ char *steps_msg;
read_bisect_terms(&term_bad, &term_good);
if (read_bisect_refs())
@@ -990,14 +990,15 @@ int bisect_next_all(const char *prefix, int no_checkout)
nr = all - reaches - 1;
steps = estimate_bisect_steps(all);
- xsnprintf(steps_msg, sizeof(steps_msg),
- Q_("(roughly %d step)", "(roughly %d steps)", steps),
- steps);
+
+ steps_msg = xstrfmt(Q_("(roughly %d step)", "(roughly %d steps)",
+ steps), steps);
/* TRANSLATORS: the last %s will be replaced with
"(roughly %d steps)" translation */
printf(Q_("Bisecting: %d revision left to test after this %s\n",
"Bisecting: %d revisions left to test after this %s\n",
nr), nr, steps_msg);
+ free(steps_msg);
return bisect_checkout(bisect_rev, no_checkout);
}
--
2.11.1
^ 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