* [PATCH 1/5] refs: Introduce pseudoref and per-worktree ref concepts
2015-07-27 20:08 [PATCH v2 0/5] pseudorefs David Turner
@ 2015-07-27 20:08 ` David Turner
2015-07-28 17:13 ` Eric Sunshine
2015-07-27 20:08 ` [PATCH 2/5] notes: replace pseudorefs with real refs David Turner
` (4 subsequent siblings)
5 siblings, 1 reply; 11+ messages in thread
From: David Turner @ 2015-07-27 20:08 UTC (permalink / raw)
To: git, mhagger, sunshine, philipoakley; +Cc: David Turner
Add glossary entries for both concepts.
Pseudorefs and per-worktree refs do not yet have special handling,
because the files refs backend already handles them correctly. Later,
we will make the LMDB backend call out to the files backend to handle
per-worktree refs.
Signed-off-by: David Turner <dturner@twopensource.com>
---
Documentation/glossary-content.txt | 21 +++++++++++++++++++++
refs.c | 23 +++++++++++++++++++++++
refs.h | 2 ++
3 files changed, 46 insertions(+)
diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt
index ab18f4b..67952f3 100644
--- a/Documentation/glossary-content.txt
+++ b/Documentation/glossary-content.txt
@@ -411,6 +411,27 @@ exclude;;
core Git. Porcelains expose more of a <<def_SCM,SCM>>
interface than the <<def_plumbing,plumbing>>.
+[[def_per_worktree_ref]]per-worktree ref::
+ Refs that are per-<<def_worktree,worktree>>, rather than
+ global. This is presently only <<def_HEAD,HEAD>>, but might
+ later include other unusual refs.
+
+[[def_pseudoref]]pseudoref::
+ Pseudorefs are a class of files under `$GIT_DIR` which behave
+ like refs for the purposes of rev-parse, but which are treated
+ specially by git. Psuedorefs both have names are all-caps,
+ and always start with a line consisting of a
+ <<def_sha1,SHA-1>> followed by whitespace. So, HEAD is not a
+ pseudoref, because it is sometimes a symbolic ref. They might
+ optionally some additional data. `MERGE_HEAD` and
+ `CHERRY_PICK_HEAD` are examples. Unlike
+ <<def_per_worktree_ref,per-worktree refs>>, these files cannot
+ be symbolic refs, and never have reflogs. They also cannot be
+ updated through the normal ref update machinery. Instead,
+ they are updated by directly writing to the files. However,
+ they can be read as if they were refs, so `git rev-parse
+ MERGE_HEAD` will work.
+
[[def_pull]]pull::
Pulling a <<def_branch,branch>> means to <<def_fetch,fetch>> it and
<<def_merge,merge>> it. See also linkgit:git-pull[1].
diff --git a/refs.c b/refs.c
index 0b96ece..0d10b7b 100644
--- a/refs.c
+++ b/refs.c
@@ -2848,6 +2848,29 @@ static int delete_ref_loose(struct ref_lock *lock, int flag, struct strbuf *err)
return 0;
}
+int is_per_worktree_ref(const char *refname)
+{
+ return !strcmp(refname, "HEAD");
+}
+
+static int is_pseudoref(const char *refname)
+{
+ const char *c;
+
+ if (strchr(refname, '/'))
+ return 0;
+
+ if (is_per_worktree_ref(refname))
+ return 0;
+
+ for (c = refname; *c; ++c) {
+ if (!isupper(*c) && *c != '-' && *c != '_')
+ return 0;
+ }
+
+ return 1;
+}
+
int delete_ref(const char *refname, const unsigned char *old_sha1,
unsigned int flags)
{
diff --git a/refs.h b/refs.h
index e4e46c3..bd5526e 100644
--- a/refs.h
+++ b/refs.h
@@ -445,6 +445,8 @@ extern int parse_hide_refs_config(const char *var, const char *value, const char
extern int ref_is_hidden(const char *);
+int is_per_worktree_ref(const char *refname);
+
enum expire_reflog_flags {
EXPIRE_REFLOGS_DRY_RUN = 1 << 0,
EXPIRE_REFLOGS_UPDATE_REF = 1 << 1,
--
2.0.4.315.gad8727a-twtrsrc
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 1/5] refs: Introduce pseudoref and per-worktree ref concepts
2015-07-27 20:08 ` [PATCH 1/5] refs: Introduce pseudoref and per-worktree ref concepts David Turner
@ 2015-07-28 17:13 ` Eric Sunshine
0 siblings, 0 replies; 11+ messages in thread
From: Eric Sunshine @ 2015-07-28 17:13 UTC (permalink / raw)
To: David Turner; +Cc: Git List, Michael Haggerty, Philip Oakley
On Mon, Jul 27, 2015 at 4:08 PM, David Turner <dturner@twopensource.com> wrote:
> refs: Introduce pseudoref and per-worktree ref concepts
>
> Add glossary entries for both concepts.
Based upon the above, I thought this was going to be a
documentation-only patch and was mildly surprised to find that it also
changed code. Perhaps:
Describe these concepts in the glossary and introduce
is_per_worktree_ref() to distinguish such files.
or something. Of course the "and" in there suggests that this might be
better off split into two patches...
More below.
> Pseudorefs and per-worktree refs do not yet have special handling,
> because the files refs backend already handles them correctly. Later,
> we will make the LMDB backend call out to the files backend to handle
> per-worktree refs.
>
> Signed-off-by: David Turner <dturner@twopensource.com>
> ---
> diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt
> index ab18f4b..67952f3 100644
> --- a/Documentation/glossary-content.txt
> +++ b/Documentation/glossary-content.txt
> @@ -411,6 +411,27 @@ exclude;;
> core Git. Porcelains expose more of a <<def_SCM,SCM>>
> interface than the <<def_plumbing,plumbing>>.
>
> +[[def_per_worktree_ref]]per-worktree ref::
> + Refs that are per-<<def_worktree,worktree>>, rather than
> + global. This is presently only <<def_HEAD,HEAD>>, but might
> + later include other unusual refs.
> +
> +[[def_pseudoref]]pseudoref::
> + Pseudorefs are a class of files under `$GIT_DIR` which behave
> + like refs for the purposes of rev-parse, but which are treated
> + specially by git. Psuedorefs both have names are all-caps,
s/names/& that/
> + and always start with a line consisting of a
> + <<def_sha1,SHA-1>> followed by whitespace. So, HEAD is not a
> + pseudoref, because it is sometimes a symbolic ref. They might
> + optionally some additional data. `MERGE_HEAD` and
s/optionally/& contain/
> + `CHERRY_PICK_HEAD` are examples. Unlike
> + <<def_per_worktree_ref,per-worktree refs>>, these files cannot
> + be symbolic refs, and never have reflogs. They also cannot be
> + updated through the normal ref update machinery. Instead,
> + they are updated by directly writing to the files. However,
> + they can be read as if they were refs, so `git rev-parse
> + MERGE_HEAD` will work.
> +
> [[def_pull]]pull::
> Pulling a <<def_branch,branch>> means to <<def_fetch,fetch>> it and
> <<def_merge,merge>> it. See also linkgit:git-pull[1].
> diff --git a/refs.c b/refs.c
> index 0b96ece..0d10b7b 100644
> --- a/refs.c
> +++ b/refs.c
> @@ -2848,6 +2848,29 @@ static int delete_ref_loose(struct ref_lock *lock, int flag, struct strbuf *err)
> return 0;
> }
>
> +int is_per_worktree_ref(const char *refname)
> +{
> + return !strcmp(refname, "HEAD");
> +}
> +
> +static int is_pseudoref(const char *refname)
> +{
> + const char *c;
> +
> + if (strchr(refname, '/'))
> + return 0;
> +
> + if (is_per_worktree_ref(refname))
> + return 0;
> +
> + for (c = refname; *c; ++c) {
> + if (!isupper(*c) && *c != '-' && *c != '_')
> + return 0;
> + }
> +
> + return 1;
> +}
This static function doesn't seem to have any callers, thus seems out
of place in this patch.
> +
> int delete_ref(const char *refname, const unsigned char *old_sha1,
> unsigned int flags)
> {
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2/5] notes: replace pseudorefs with real refs
2015-07-27 20:08 [PATCH v2 0/5] pseudorefs David Turner
2015-07-27 20:08 ` [PATCH 1/5] refs: Introduce pseudoref and per-worktree ref concepts David Turner
@ 2015-07-27 20:08 ` David Turner
2015-07-27 20:08 ` [PATCH 3/5] pseudorefs: create and use pseudoref update and delete functions David Turner
` (3 subsequent siblings)
5 siblings, 0 replies; 11+ messages in thread
From: David Turner @ 2015-07-27 20:08 UTC (permalink / raw)
To: git, mhagger, sunshine, philipoakley; +Cc: David Turner
All-caps files like NOTES_MERGE_REF are pseudorefs, and thus are
per-worktree. We don't want multiple notes merges happening at once
(in different worktrees), so we want to make these refs true refs.
So, we lowercase NOTES_MERGE_REF and friends. That way, backends
that distinguish between pseudorefs and real refs can correctly
handle notes merges.
This will also enable us to prevent pseudorefs from being updated by
the ref update machinery e.g. git update-ref.
Signed-off-by: David Turner <dturner@twopensource.com>
---
Documentation/git-notes.txt | 12 ++---
builtin/notes.c | 38 ++++++++--------
notes-merge.c | 10 ++--
notes-merge.h | 8 ++--
t/t3310-notes-merge-manual-resolve.sh | 86 +++++++++++++++++------------------
t/t3311-notes-merge-fanout.sh | 6 +--
6 files changed, 80 insertions(+), 80 deletions(-)
diff --git a/Documentation/git-notes.txt b/Documentation/git-notes.txt
index 851518d..82fa3fd 100644
--- a/Documentation/git-notes.txt
+++ b/Documentation/git-notes.txt
@@ -103,7 +103,7 @@ merge::
If conflicts arise and a strategy for automatically resolving
conflicting notes (see the -s/--strategy option) is not given,
the "manual" resolver is used. This resolver checks out the
-conflicting notes in a special worktree (`.git/NOTES_MERGE_WORKTREE`),
+conflicting notes in a special worktree (`.git/notes_merge_worktree`),
and instructs the user to manually resolve the conflicts there.
When done, the user can either finalize the merge with
'git notes merge --commit', or abort the merge with
@@ -189,11 +189,11 @@ OPTIONS
--commit::
Finalize an in-progress 'git notes merge'. Use this option
when you have resolved the conflicts that 'git notes merge'
- stored in .git/NOTES_MERGE_WORKTREE. This amends the partial
+ stored in .git/notes_merge_worktree. This amends the partial
merge commit created by 'git notes merge' (stored in
- .git/NOTES_MERGE_PARTIAL) by adding the notes in
- .git/NOTES_MERGE_WORKTREE. The notes ref stored in the
- .git/NOTES_MERGE_REF symref is updated to the resulting commit.
+ .git/notes_merge_partial) by adding the notes in
+ .git/notes_merge_worktree. The notes ref stored in the
+ .git/notes_merge_ref symref is updated to the resulting commit.
--abort::
Abort/reset a in-progress 'git notes merge', i.e. a notes merge
@@ -241,7 +241,7 @@ NOTES MERGE STRATEGIES
The default notes merge strategy is "manual", which checks out
conflicting notes in a special work tree for resolving notes conflicts
-(`.git/NOTES_MERGE_WORKTREE`), and instructs the user to resolve the
+(`.git/notes_merge_worktree`), and instructs the user to resolve the
conflicts in that work tree.
When done, the user can either finalize the merge with
'git notes merge --commit', or abort the merge with
diff --git a/builtin/notes.c b/builtin/notes.c
index 63f95fc..e0b8a02 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -670,14 +670,14 @@ static int merge_abort(struct notes_merge_options *o)
int ret = 0;
/*
- * Remove .git/NOTES_MERGE_PARTIAL and .git/NOTES_MERGE_REF, and call
- * notes_merge_abort() to remove .git/NOTES_MERGE_WORKTREE.
+ * Remove .git/notes_merge_partial and .git/notes_merge_ref, and call
+ * notes_merge_abort() to remove .git/notes_merge_worktree.
*/
- if (delete_ref("NOTES_MERGE_PARTIAL", NULL, 0))
- ret += error("Failed to delete ref NOTES_MERGE_PARTIAL");
- if (delete_ref("NOTES_MERGE_REF", NULL, REF_NODEREF))
- ret += error("Failed to delete ref NOTES_MERGE_REF");
+ if (delete_ref("notes_merge_partial", NULL, 0))
+ ret += error("Failed to delete ref notes_merge_partial");
+ if (delete_ref("notes_merge_ref", NULL, REF_NODEREF))
+ ret += error("Failed to delete ref notes_merge_ref");
if (notes_merge_abort(o))
ret += error("Failed to remove 'git notes merge' worktree");
return ret;
@@ -694,16 +694,16 @@ static int merge_commit(struct notes_merge_options *o)
int ret;
/*
- * Read partial merge result from .git/NOTES_MERGE_PARTIAL,
- * and target notes ref from .git/NOTES_MERGE_REF.
+ * Read partial merge result from .git/notes_merge_partial,
+ * and target notes ref from .git/notes_merge_ref.
*/
- if (get_sha1("NOTES_MERGE_PARTIAL", sha1))
- die("Failed to read ref NOTES_MERGE_PARTIAL");
+ if (get_sha1("notes_merge_partial", sha1))
+ die("Failed to read ref notes_merge_partial");
else if (!(partial = lookup_commit_reference(sha1)))
- die("Could not find commit from NOTES_MERGE_PARTIAL.");
+ die("Could not find commit from notes_merge_partial.");
else if (parse_commit(partial))
- die("Could not parse commit from NOTES_MERGE_PARTIAL.");
+ die("Could not parse commit from notes_merge_partial.");
if (partial->parents)
hashcpy(parent_sha1, partial->parents->item->object.sha1);
@@ -711,12 +711,12 @@ static int merge_commit(struct notes_merge_options *o)
hashclr(parent_sha1);
t = xcalloc(1, sizeof(struct notes_tree));
- init_notes(t, "NOTES_MERGE_PARTIAL", combine_notes_overwrite, 0);
+ init_notes(t, "notes_merge_partial", combine_notes_overwrite, 0);
o->local_ref = local_ref_to_free =
- resolve_refdup("NOTES_MERGE_REF", 0, sha1, NULL);
+ resolve_refdup("notes_merge_ref", 0, sha1, NULL);
if (!o->local_ref)
- die("Failed to resolve NOTES_MERGE_REF");
+ die("Failed to resolve notes_merge_ref");
if (notes_merge_commit(o, t, partial, sha1))
die("Failed to finalize notes merge");
@@ -825,11 +825,11 @@ static int merge(int argc, const char **argv, const char *prefix)
update_ref(msg.buf, default_notes_ref(), result_sha1, NULL,
0, UPDATE_REFS_DIE_ON_ERR);
else { /* Merge has unresolved conflicts */
- /* Update .git/NOTES_MERGE_PARTIAL with partial merge result */
- update_ref(msg.buf, "NOTES_MERGE_PARTIAL", result_sha1, NULL,
+ /* Update .git/notes_merge_partial with partial merge result */
+ update_ref(msg.buf, "notes_merge_partial", result_sha1, NULL,
0, UPDATE_REFS_DIE_ON_ERR);
- /* Store ref-to-be-updated into .git/NOTES_MERGE_REF */
- if (create_symref("NOTES_MERGE_REF", default_notes_ref(), NULL))
+ /* Store ref-to-be-updated into .git/notes_merge_ref */
+ if (create_symref("notes_merge_ref", default_notes_ref(), NULL))
die("Failed to store link to current notes ref (%s)",
default_notes_ref());
printf("Automatic notes merge failed. Fix conflicts in %s and "
diff --git a/notes-merge.c b/notes-merge.c
index 0b2b82c..58a8637 100644
--- a/notes-merge.c
+++ b/notes-merge.c
@@ -274,10 +274,10 @@ static void check_notes_merge_worktree(struct notes_merge_options *o)
"'git notes merge --commit' or 'git notes "
"merge --abort' to commit/abort the "
"previous merge before you start a new "
- "notes merge.", git_path("NOTES_MERGE_*"));
+ "notes merge.", git_path("notes_merge_*"));
else
die("You have not concluded your notes merge "
- "(%s exists).", git_path("NOTES_MERGE_*"));
+ "(%s exists).", git_path("notes_merge_*"));
}
if (safe_create_leading_directories_const(git_path(
@@ -663,7 +663,7 @@ int notes_merge_commit(struct notes_merge_options *o,
unsigned char *result_sha1)
{
/*
- * Iterate through files in .git/NOTES_MERGE_WORKTREE and add all
+ * Iterate through files in .git/notes_merge_workree and add all
* found notes to 'partial_tree'. Write the updated notes tree to
* the DB, and commit the resulting tree object while reusing the
* commit message and parents from 'partial_commit'.
@@ -734,8 +734,8 @@ int notes_merge_commit(struct notes_merge_options *o,
int notes_merge_abort(struct notes_merge_options *o)
{
/*
- * Remove all files within .git/NOTES_MERGE_WORKTREE. We do not remove
- * the .git/NOTES_MERGE_WORKTREE directory itself, since it might be
+ * Remove all files within .git/notes_merge_workree. We do not remove
+ * the .git/notes_merge_workree directory itself, since it might be
* the current working directory of the user.
*/
struct strbuf buf = STRBUF_INIT;
diff --git a/notes-merge.h b/notes-merge.h
index 1d01f6a..18705d6 100644
--- a/notes-merge.h
+++ b/notes-merge.h
@@ -1,7 +1,7 @@
#ifndef NOTES_MERGE_H
#define NOTES_MERGE_H
-#define NOTES_MERGE_WORKTREE "NOTES_MERGE_WORKTREE"
+#define NOTES_MERGE_WORKTREE "notes_merge_worktree"
enum notes_merge_verbosity {
NOTES_MERGE_VERBOSITY_DEFAULT = 2,
@@ -46,7 +46,7 @@ void init_notes_merge_options(struct notes_merge_options *o);
* are stored in 'local_tree', and the SHA1 or the resulting commit
* (to be amended when the conflicts have been resolved) is written into
* 'result_sha1'. The unmerged entries are written into the
- * .git/NOTES_MERGE_WORKTREE directory with conflict markers.
+ * .git/notes_merge_worktree directory with conflict markers.
* -1 is returned.
*
* Both o->local_ref and o->remote_ref must be given (non-NULL), but either ref
@@ -65,7 +65,7 @@ int notes_merge(struct notes_merge_options *o,
* the given 'partial_commit', the partial result commit created by a previous
* call to notes_merge().
*
- * This function will add the (now resolved) notes in .git/NOTES_MERGE_WORKTREE
+ * This function will add the (now resolved) notes in .git/notes_merge_worktree
* to 'partial_tree', and create a final notes merge commit, the SHA1 of which
* will be stored in 'result_sha1'.
*/
@@ -77,7 +77,7 @@ int notes_merge_commit(struct notes_merge_options *o,
/*
* Abort conflict resolution from an earlier notes_merge()
*
- * Removes the notes merge worktree in .git/NOTES_MERGE_WORKTREE.
+ * Removes the notes merge worktree in .git/notes_merge_worktree.
*/
int notes_merge_abort(struct notes_merge_options *o);
diff --git a/t/t3310-notes-merge-manual-resolve.sh b/t/t3310-notes-merge-manual-resolve.sh
index 195bb97..dc9ecd5 100755
--- a/t/t3310-notes-merge-manual-resolve.sh
+++ b/t/t3310-notes-merge-manual-resolve.sh
@@ -178,12 +178,12 @@ test_expect_success 'merge z into m (== y) with default ("manual") resolver => C
git config core.notesRef refs/notes/m &&
test_must_fail git notes merge z >output &&
# Output should point to where to resolve conflicts
- grep -q "\\.git/NOTES_MERGE_WORKTREE" output &&
+ grep -q "\\.git/notes_merge_worktree" output &&
# Inspect merge conflicts
- ls .git/NOTES_MERGE_WORKTREE >output_conflicts &&
+ ls .git/notes_merge_worktree >output_conflicts &&
test_cmp expect_conflicts output_conflicts &&
( for f in $(cat expect_conflicts); do
- test_cmp "expect_conflict_$f" ".git/NOTES_MERGE_WORKTREE/$f" ||
+ test_cmp "expect_conflict_$f" ".git/notes_merge_worktree/$f" ||
exit 1
done ) &&
# Verify that current notes tree (pre-merge) has not changed (m == y)
@@ -222,10 +222,10 @@ test_expect_success 'change notes in z' '
'
test_expect_success 'cannot do merge w/conflicts when previous merge is unfinished' '
- test -d .git/NOTES_MERGE_WORKTREE &&
+ test -d .git/notes_merge_worktree &&
test_must_fail git notes merge z >output 2>&1 &&
# Output should indicate what is wrong
- grep -q "\\.git/NOTES_MERGE_\\* exists" output
+ grep -q "\\.git/notes_merge_\\* exists" output
'
# Setup non-conflicting merge between x and new notes ref w
@@ -282,7 +282,7 @@ w notes on 1st commit
EOF
test_expect_success 'can do merge without conflicts even if previous merge is unfinished (x => w)' '
- test -d .git/NOTES_MERGE_WORKTREE &&
+ test -d .git/notes_merge_worktree &&
git notes merge x &&
verify_notes w &&
# Verify that other notes refs has not changed (x and y)
@@ -316,15 +316,15 @@ EOF
test_expect_success 'finalize conflicting merge (z => m)' '
# Resolve conflicts and finalize merge
- cat >.git/NOTES_MERGE_WORKTREE/$commit_sha1 <<EOF &&
+ cat >.git/notes_merge_worktree/$commit_sha1 <<EOF &&
y and z notes on 1st commit
EOF
- cat >.git/NOTES_MERGE_WORKTREE/$commit_sha4 <<EOF &&
+ cat >.git/notes_merge_worktree/$commit_sha4 <<EOF &&
y and z notes on 4th commit
EOF
git notes merge --commit &&
- # No .git/NOTES_MERGE_* files left
- test_might_fail ls .git/NOTES_MERGE_* >output 2>/dev/null &&
+ # No .git/notes_merge_* files left
+ test_might_fail ls .git/notes_merge_* >output 2>/dev/null &&
test_cmp /dev/null output &&
# Merge commit has pre-merge y and pre-merge z as parents
test "$(git rev-parse refs/notes/m^1)" = "$(cat pre_merge_y)" &&
@@ -369,12 +369,12 @@ test_expect_success 'redo merge of z into m (== y) with default ("manual") resol
git config core.notesRef refs/notes/m &&
test_must_fail git notes merge z >output &&
# Output should point to where to resolve conflicts
- grep -q "\\.git/NOTES_MERGE_WORKTREE" output &&
+ grep -q "\\.git/notes_merge_worktree" output &&
# Inspect merge conflicts
- ls .git/NOTES_MERGE_WORKTREE >output_conflicts &&
+ ls .git/notes_merge_worktree >output_conflicts &&
test_cmp expect_conflicts output_conflicts &&
( for f in $(cat expect_conflicts); do
- test_cmp "expect_conflict_$f" ".git/NOTES_MERGE_WORKTREE/$f" ||
+ test_cmp "expect_conflict_$f" ".git/notes_merge_worktree/$f" ||
exit 1
done ) &&
# Verify that current notes tree (pre-merge) has not changed (m == y)
@@ -385,8 +385,8 @@ test_expect_success 'redo merge of z into m (== y) with default ("manual") resol
test_expect_success 'abort notes merge' '
git notes merge --abort &&
- # No .git/NOTES_MERGE_* files left
- test_might_fail ls .git/NOTES_MERGE_* >output 2>/dev/null &&
+ # No .git/notes_merge_* files left
+ test_might_fail ls .git/notes_merge_* >output 2>/dev/null &&
test_cmp /dev/null output &&
# m has not moved (still == y)
test "$(git rev-parse refs/notes/m)" = "$(cat pre_merge_y)" &&
@@ -403,12 +403,12 @@ git rev-parse refs/notes/z > pre_merge_z
test_expect_success 'redo merge of z into m (== y) with default ("manual") resolver => Conflicting 3-way merge' '
test_must_fail git notes merge z >output &&
# Output should point to where to resolve conflicts
- grep -q "\\.git/NOTES_MERGE_WORKTREE" output &&
+ grep -q "\\.git/notes_merge_worktree" output &&
# Inspect merge conflicts
- ls .git/NOTES_MERGE_WORKTREE >output_conflicts &&
+ ls .git/notes_merge_worktree >output_conflicts &&
test_cmp expect_conflicts output_conflicts &&
( for f in $(cat expect_conflicts); do
- test_cmp "expect_conflict_$f" ".git/NOTES_MERGE_WORKTREE/$f" ||
+ test_cmp "expect_conflict_$f" ".git/notes_merge_worktree/$f" ||
exit 1
done ) &&
# Verify that current notes tree (pre-merge) has not changed (m == y)
@@ -441,19 +441,19 @@ EOF
test_expect_success 'add + remove notes in finalized merge (z => m)' '
# Resolve one conflict
- cat >.git/NOTES_MERGE_WORKTREE/$commit_sha1 <<EOF &&
+ cat >.git/notes_merge_worktree/$commit_sha1 <<EOF &&
y and z notes on 1st commit
EOF
# Remove another conflict
- rm .git/NOTES_MERGE_WORKTREE/$commit_sha4 &&
+ rm .git/notes_merge_worktree/$commit_sha4 &&
# Remove a D/F conflict
- rm .git/NOTES_MERGE_WORKTREE/$commit_sha3 &&
+ rm .git/notes_merge_worktree/$commit_sha3 &&
# Add a new note
- echo "new note on 5th commit" > .git/NOTES_MERGE_WORKTREE/$commit_sha5 &&
+ echo "new note on 5th commit" > .git/notes_merge_worktree/$commit_sha5 &&
# Finalize merge
git notes merge --commit &&
- # No .git/NOTES_MERGE_* files left
- test_might_fail ls .git/NOTES_MERGE_* >output 2>/dev/null &&
+ # No .git/notes_merge_* files left
+ test_might_fail ls .git/notes_merge_* >output 2>/dev/null &&
test_cmp /dev/null output &&
# Merge commit has pre-merge y and pre-merge z as parents
test "$(git rev-parse refs/notes/m^1)" = "$(cat pre_merge_y)" &&
@@ -484,12 +484,12 @@ test_expect_success 'redo merge of z into m (== y) with default ("manual") resol
git update-ref refs/notes/m refs/notes/y &&
test_must_fail git notes merge z >output &&
# Output should point to where to resolve conflicts
- grep -q "\\.git/NOTES_MERGE_WORKTREE" output &&
+ grep -q "\\.git/notes_merge_worktree" output &&
# Inspect merge conflicts
- ls .git/NOTES_MERGE_WORKTREE >output_conflicts &&
+ ls .git/notes_merge_worktree >output_conflicts &&
test_cmp expect_conflicts output_conflicts &&
( for f in $(cat expect_conflicts); do
- test_cmp "expect_conflict_$f" ".git/NOTES_MERGE_WORKTREE/$f" ||
+ test_cmp "expect_conflict_$f" ".git/notes_merge_worktree/$f" ||
exit 1
done ) &&
# Verify that current notes tree (pre-merge) has not changed (m == y)
@@ -507,31 +507,31 @@ test_expect_success 'reset notes ref m to somewhere else (w)' '
test "$(git rev-parse refs/notes/m)" = "$(git rev-parse refs/notes/w)"
'
-test_expect_success 'fail to finalize conflicting merge if underlying ref has moved in the meantime (m != NOTES_MERGE_PARTIAL^1)' '
+test_expect_success 'fail to finalize conflicting merge if underlying ref has moved in the meantime (m != notes_merge_partial^1)' '
# Resolve conflicts
- cat >.git/NOTES_MERGE_WORKTREE/$commit_sha1 <<EOF &&
+ cat >.git/notes_merge_worktree/$commit_sha1 <<EOF &&
y and z notes on 1st commit
EOF
- cat >.git/NOTES_MERGE_WORKTREE/$commit_sha4 <<EOF &&
+ cat >.git/notes_merge_worktree/$commit_sha4 <<EOF &&
y and z notes on 4th commit
EOF
# Fail to finalize merge
test_must_fail git notes merge --commit >output 2>&1 &&
- # .git/NOTES_MERGE_* must remain
- test -f .git/NOTES_MERGE_PARTIAL &&
- test -f .git/NOTES_MERGE_REF &&
- test -f .git/NOTES_MERGE_WORKTREE/$commit_sha1 &&
- test -f .git/NOTES_MERGE_WORKTREE/$commit_sha2 &&
- test -f .git/NOTES_MERGE_WORKTREE/$commit_sha3 &&
- test -f .git/NOTES_MERGE_WORKTREE/$commit_sha4 &&
+ # .git/notes_merge_* must remain
+ git rev-parse --verify notes_merge_partial &&
+ git rev-parse --verify notes_merge_ref &&
+ test -f .git/notes_merge_worktree/$commit_sha1 &&
+ test -f .git/notes_merge_worktree/$commit_sha2 &&
+ test -f .git/notes_merge_worktree/$commit_sha3 &&
+ test -f .git/notes_merge_worktree/$commit_sha4 &&
# Refs are unchanged
test "$(git rev-parse refs/notes/m)" = "$(git rev-parse refs/notes/w)" &&
- test "$(git rev-parse refs/notes/y)" = "$(git rev-parse NOTES_MERGE_PARTIAL^1)" &&
- test "$(git rev-parse refs/notes/m)" != "$(git rev-parse NOTES_MERGE_PARTIAL^1)" &&
+ test "$(git rev-parse refs/notes/y)" = "$(git rev-parse notes_merge_partial^1)" &&
+ test "$(git rev-parse refs/notes/m)" != "$(git rev-parse notes_merge_partial^1)" &&
# Mention refs/notes/m, and its current and expected value in output
grep -q "refs/notes/m" output &&
grep -q "$(git rev-parse refs/notes/m)" output &&
- grep -q "$(git rev-parse NOTES_MERGE_PARTIAL^1)" output &&
+ grep -q "$(git rev-parse notes_merge_partial^1)" output &&
# Verify that other notes refs has not changed (w, x, y and z)
verify_notes w &&
verify_notes x &&
@@ -541,8 +541,8 @@ EOF
test_expect_success 'resolve situation by aborting the notes merge' '
git notes merge --abort &&
- # No .git/NOTES_MERGE_* files left
- test_might_fail ls .git/NOTES_MERGE_* >output 2>/dev/null &&
+ # No .git/notes_merge_* files left
+ test_might_fail ls .git/notes_merge_* >output 2>/dev/null &&
test_cmp /dev/null output &&
# m has not moved (still == w)
test "$(git rev-parse refs/notes/m)" = "$(git rev-parse refs/notes/w)" &&
@@ -563,7 +563,7 @@ test_expect_success 'switch cwd before committing notes merge' '
git notes --ref=other add -m bar HEAD &&
test_must_fail git notes merge refs/notes/other &&
(
- cd .git/NOTES_MERGE_WORKTREE &&
+ cd .git/notes_merge_worktree &&
echo "foo" > $(git rev-parse HEAD) &&
echo "bar" >> $(git rev-parse HEAD) &&
git notes merge --commit
diff --git a/t/t3311-notes-merge-fanout.sh b/t/t3311-notes-merge-fanout.sh
index 93516ef..eeaea62 100755
--- a/t/t3311-notes-merge-fanout.sh
+++ b/t/t3311-notes-merge-fanout.sh
@@ -387,10 +387,10 @@ other notes for commit4
EOF
test_expect_success 'verify conflict entries (with no fanout)' '
- ls .git/NOTES_MERGE_WORKTREE >output_conflicts &&
+ ls .git/notes_merge_worktree >output_conflicts &&
test_cmp expect_conflicts output_conflicts &&
( for f in $(cat expect_conflicts); do
- test_cmp "expect_conflict_$f" ".git/NOTES_MERGE_WORKTREE/$f" ||
+ test_cmp "expect_conflict_$f" ".git/notes_merge_worktree/$f" ||
exit 1
done ) &&
# Verify that current notes tree (pre-merge) has not changed (m == w)
@@ -417,7 +417,7 @@ other notes for commit1
EOF
test_expect_success 'resolve and finalize merge (z => w)' '
- cat >.git/NOTES_MERGE_WORKTREE/$commit_sha3 <<EOF &&
+ cat >.git/notes_merge_worktree/$commit_sha3 <<EOF &&
other notes for commit3
appended notes for commit3
--
2.0.4.315.gad8727a-twtrsrc
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 3/5] pseudorefs: create and use pseudoref update and delete functions
2015-07-27 20:08 [PATCH v2 0/5] pseudorefs David Turner
2015-07-27 20:08 ` [PATCH 1/5] refs: Introduce pseudoref and per-worktree ref concepts David Turner
2015-07-27 20:08 ` [PATCH 2/5] notes: replace pseudorefs with real refs David Turner
@ 2015-07-27 20:08 ` David Turner
2015-07-28 0:49 ` David Turner
2015-07-27 20:08 ` [PATCH 4/5] rebase: use update_ref David Turner
` (2 subsequent siblings)
5 siblings, 1 reply; 11+ messages in thread
From: David Turner @ 2015-07-27 20:08 UTC (permalink / raw)
To: git, mhagger, sunshine, philipoakley; +Cc: David Turner
Pseudorefs should not be updated through the ref transaction
API, because alternate ref backends still need to store pseudorefs
in GIT_DIR (instead of wherever they store refs). Instead,
change update_ref and delete_ref to call pseudoref-specific
functions.
Signed-off-by: David Turner <dturner@twopensource.com>
---
refs.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 92 insertions(+), 8 deletions(-)
diff --git a/refs.c b/refs.c
index 0d10b7b..119ac9c 100644
--- a/refs.c
+++ b/refs.c
@@ -2871,12 +2871,87 @@ static int is_pseudoref(const char *refname)
return 1;
}
+static int write_pseudoref(const char *pseudoref, const unsigned char *sha1,
+ const unsigned char *old_sha1, struct strbuf *err)
+{
+ const char *filename;
+ int fd;
+ static struct lock_file lock;
+ struct strbuf buf = STRBUF_INIT;
+ int ret = -1;
+
+ strbuf_addf(&buf, "%s\n", sha1_to_hex(sha1));
+
+ filename = git_path("%s", pseudoref);
+ fd = hold_lock_file_for_update(&lock, filename, LOCK_DIE_ON_ERROR);
+ if (fd < 0) {
+ strbuf_addf(err, "Could not open '%s' for writing: %s",
+ filename, strerror(errno));
+ return -1;
+ }
+
+ if (old_sha1) {
+ unsigned char actual_old_sha1[20];
+ read_ref(pseudoref, actual_old_sha1);
+ if (hashcmp(actual_old_sha1, old_sha1)) {
+ strbuf_addf(err, "Unexpected sha1 when writing %s", pseudoref);
+ rollback_lock_file(&lock);
+ goto done;
+ }
+ }
+
+ if (write_in_full(fd, buf.buf, buf.len) != buf.len) {
+ strbuf_addf(err, "Could not write to '%s'", filename);
+ rollback_lock_file(&lock);
+ goto done;
+ }
+
+ commit_lock_file(&lock);
+ ret = 0;
+done:
+ strbuf_release(&buf);
+ return ret;
+}
+
+static int delete_pseudoref(const char *pseudoref, const unsigned char *old_sha1)
+{
+ static struct lock_file lock;
+ const char *filename;
+
+ filename = git_path("%s", pseudoref);
+
+ if (old_sha1 && !is_null_sha1(old_sha1)) {
+ int fd;
+ unsigned char actual_old_sha1[20];
+
+ fd = hold_lock_file_for_update(&lock, filename,
+ LOCK_DIE_ON_ERROR);
+ if (fd < 0)
+ die_errno(_("Could not open '%s' for writing"), filename);
+ read_ref(pseudoref, actual_old_sha1);
+ if (hashcmp(actual_old_sha1, old_sha1)) {
+ warning("Unexpected sha1 when deleting %s", pseudoref);
+ return -1;
+ }
+
+ unlink(filename);
+ rollback_lock_file(&lock);
+ } else {
+ unlink(filename);
+ }
+
+ return 0;
+}
+
int delete_ref(const char *refname, const unsigned char *old_sha1,
unsigned int flags)
{
struct ref_transaction *transaction;
struct strbuf err = STRBUF_INIT;
+ if (is_pseudoref(refname))
+ return delete_pseudoref(refname, old_sha1);
+
transaction = ref_transaction_begin(&err);
if (!transaction ||
ref_transaction_delete(transaction, refname, old_sha1,
@@ -3970,17 +4045,25 @@ int update_ref(const char *msg, const char *refname,
const unsigned char *new_sha1, const unsigned char *old_sha1,
unsigned int flags, enum action_on_err onerr)
{
- struct ref_transaction *t;
+ struct ref_transaction *t = NULL;
struct strbuf err = STRBUF_INIT;
+ int ret = 0;
- t = ref_transaction_begin(&err);
- if (!t ||
- ref_transaction_update(t, refname, new_sha1, old_sha1,
- flags, msg, &err) ||
- ref_transaction_commit(t, &err)) {
+ if (is_pseudoref(refname) && 0) {
+ ret = write_pseudoref(refname, new_sha1, old_sha1, &err);
+ } else {
+ t = ref_transaction_begin(&err);
+ if (!t ||
+ ref_transaction_update(t, refname, new_sha1, old_sha1,
+ flags, msg, &err) ||
+ ref_transaction_commit(t, &err)) {
+ ret = 1;
+ ref_transaction_free(t);
+ }
+ }
+ if (ret) {
const char *str = "update_ref failed for ref '%s': %s";
- ref_transaction_free(t);
switch (onerr) {
case UPDATE_REFS_MSG_ON_ERR:
error(str, refname, err.buf);
@@ -3995,7 +4078,8 @@ int update_ref(const char *msg, const char *refname,
return 1;
}
strbuf_release(&err);
- ref_transaction_free(t);
+ if (t)
+ ref_transaction_free(t);
return 0;
}
--
2.0.4.315.gad8727a-twtrsrc
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 4/5] rebase: use update_ref
2015-07-27 20:08 [PATCH v2 0/5] pseudorefs David Turner
` (2 preceding siblings ...)
2015-07-27 20:08 ` [PATCH 3/5] pseudorefs: create and use pseudoref update and delete functions David Turner
@ 2015-07-27 20:08 ` David Turner
2015-07-28 18:18 ` Junio C Hamano
2015-07-27 20:08 ` [PATCH 5/5] sequencer: replace write_cherry_pick_head with update_ref David Turner
2015-07-27 22:04 ` [PATCH v2 0/5] pseudorefs Junio C Hamano
5 siblings, 1 reply; 11+ messages in thread
From: David Turner @ 2015-07-27 20:08 UTC (permalink / raw)
To: git, mhagger, sunshine, philipoakley; +Cc: David Turner
Instead of manually writing a pseudoref (in one case) and shelling out
to git update-ref (in another), use the update_ref function. This
is much simpler.
Signed-off-by: David Turner <dturner@twopensource.com>
---
bisect.c | 37 ++++++++-----------------------------
1 file changed, 8 insertions(+), 29 deletions(-)
diff --git a/bisect.c b/bisect.c
index 857cf59..33ac88d 100644
--- a/bisect.c
+++ b/bisect.c
@@ -19,7 +19,6 @@ static struct object_id *current_bad_oid;
static const char *argv_checkout[] = {"checkout", "-q", NULL, "--", NULL};
static const char *argv_show_branch[] = {"show-branch", NULL, NULL};
-static const char *argv_update_ref[] = {"update-ref", "--no-deref", "BISECT_HEAD", NULL, NULL};
static const char *term_bad;
static const char *term_good;
@@ -675,34 +674,16 @@ static int is_expected_rev(const struct object_id *oid)
return res;
}
-static void mark_expected_rev(char *bisect_rev_hex)
-{
- int len = strlen(bisect_rev_hex);
- const char *filename = git_path("BISECT_EXPECTED_REV");
- int fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600);
-
- if (fd < 0)
- die_errno("could not create file '%s'", filename);
-
- bisect_rev_hex[len] = '\n';
- write_or_die(fd, bisect_rev_hex, len + 1);
- bisect_rev_hex[len] = '\0';
-
- if (close(fd) < 0)
- die("closing file %s: %s", filename, strerror(errno));
-}
-
-static int bisect_checkout(char *bisect_rev_hex, int no_checkout)
+static int bisect_checkout(const unsigned char *bisect_rev, int no_checkout)
{
+ char bisect_rev_hex[GIT_SHA1_HEXSZ + 1];
- mark_expected_rev(bisect_rev_hex);
+ memcpy(bisect_rev_hex, sha1_to_hex(bisect_rev), GIT_SHA1_HEXSZ + 1);
+ update_ref(NULL, "BISECT_EXPECTED_REV", bisect_rev, NULL, 0, UPDATE_REFS_DIE_ON_ERR);
argv_checkout[2] = bisect_rev_hex;
if (no_checkout) {
- argv_update_ref[3] = bisect_rev_hex;
- if (run_command_v_opt(argv_update_ref, RUN_GIT_CMD))
- die("update-ref --no-deref HEAD failed on %s",
- bisect_rev_hex);
+ update_ref(NULL, "BISECT_HEAD", bisect_rev, NULL, 0, UPDATE_REFS_DIE_ON_ERR);
} else {
int res;
res = run_command_v_opt(argv_checkout, RUN_GIT_CMD);
@@ -804,7 +785,7 @@ static void check_merge_bases(int no_checkout)
handle_skipped_merge_base(mb);
} else {
printf("Bisecting: a merge base must be tested\n");
- exit(bisect_checkout(sha1_to_hex(mb), no_checkout));
+ exit(bisect_checkout(mb, no_checkout));
}
}
@@ -948,7 +929,6 @@ 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 bisect_rev_hex[GIT_SHA1_HEXSZ + 1];
read_bisect_terms(&term_bad, &term_good);
if (read_bisect_refs())
@@ -986,11 +966,10 @@ int bisect_next_all(const char *prefix, int no_checkout)
}
bisect_rev = revs.commits->item->object.sha1;
- memcpy(bisect_rev_hex, sha1_to_hex(bisect_rev), GIT_SHA1_HEXSZ + 1);
if (!hashcmp(bisect_rev, current_bad_oid->hash)) {
exit_if_skipped_commits(tried, current_bad_oid);
- printf("%s is the first %s commit\n", bisect_rev_hex,
+ printf("%s is the first %s commit\n", sha1_to_hex(bisect_rev),
term_bad);
show_diff_tree(prefix, revs.commits->item);
/* This means the bisection process succeeded. */
@@ -1003,7 +982,7 @@ int bisect_next_all(const char *prefix, int no_checkout)
"(roughly %d step%s)\n", nr, (nr == 1 ? "" : "s"),
steps, (steps == 1 ? "" : "s"));
- return bisect_checkout(bisect_rev_hex, no_checkout);
+ return bisect_checkout(bisect_rev, no_checkout);
}
static inline int log2i(int n)
--
2.0.4.315.gad8727a-twtrsrc
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 4/5] rebase: use update_ref
2015-07-27 20:08 ` [PATCH 4/5] rebase: use update_ref David Turner
@ 2015-07-28 18:18 ` Junio C Hamano
2015-07-28 18:53 ` David Turner
0 siblings, 1 reply; 11+ messages in thread
From: Junio C Hamano @ 2015-07-28 18:18 UTC (permalink / raw)
To: David Turner; +Cc: git, mhagger, sunshine, philipoakley
David Turner <dturner@twopensource.com> writes:
> Instead of manually writing a pseudoref (in one case) and shelling out
> to git update-ref (in another), use the update_ref function. This
> is much simpler.
>
> Signed-off-by: David Turner <dturner@twopensource.com>
> ---
> bisect.c | 37 ++++++++-----------------------------
> 1 file changed, 8 insertions(+), 29 deletions(-)
Mistitled? I can do s/rebase/bisect/ at my end if that is all
needed.
>
> diff --git a/bisect.c b/bisect.c
> index 857cf59..33ac88d 100644
> --- a/bisect.c
> +++ b/bisect.c
> @@ -19,7 +19,6 @@ static struct object_id *current_bad_oid;
>
> static const char *argv_checkout[] = {"checkout", "-q", NULL, "--", NULL};
> static const char *argv_show_branch[] = {"show-branch", NULL, NULL};
> -static const char *argv_update_ref[] = {"update-ref", "--no-deref", "BISECT_HEAD", NULL, NULL};
>
> static const char *term_bad;
> static const char *term_good;
> @@ -675,34 +674,16 @@ static int is_expected_rev(const struct object_id *oid)
> return res;
> }
>
> -static void mark_expected_rev(char *bisect_rev_hex)
> -{
> - int len = strlen(bisect_rev_hex);
> - const char *filename = git_path("BISECT_EXPECTED_REV");
> - int fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600);
> -
> - if (fd < 0)
> - die_errno("could not create file '%s'", filename);
> -
> - bisect_rev_hex[len] = '\n';
> - write_or_die(fd, bisect_rev_hex, len + 1);
> - bisect_rev_hex[len] = '\0';
> -
> - if (close(fd) < 0)
> - die("closing file %s: %s", filename, strerror(errno));
> -}
> -
> -static int bisect_checkout(char *bisect_rev_hex, int no_checkout)
> +static int bisect_checkout(const unsigned char *bisect_rev, int no_checkout)
> {
> + char bisect_rev_hex[GIT_SHA1_HEXSZ + 1];
>
> - mark_expected_rev(bisect_rev_hex);
> + memcpy(bisect_rev_hex, sha1_to_hex(bisect_rev), GIT_SHA1_HEXSZ + 1);
> + update_ref(NULL, "BISECT_EXPECTED_REV", bisect_rev, NULL, 0, UPDATE_REFS_DIE_ON_ERR);
>
> argv_checkout[2] = bisect_rev_hex;
> if (no_checkout) {
> - argv_update_ref[3] = bisect_rev_hex;
> - if (run_command_v_opt(argv_update_ref, RUN_GIT_CMD))
> - die("update-ref --no-deref HEAD failed on %s",
> - bisect_rev_hex);
> + update_ref(NULL, "BISECT_HEAD", bisect_rev, NULL, 0, UPDATE_REFS_DIE_ON_ERR);
> } else {
> int res;
> res = run_command_v_opt(argv_checkout, RUN_GIT_CMD);
> @@ -804,7 +785,7 @@ static void check_merge_bases(int no_checkout)
> handle_skipped_merge_base(mb);
> } else {
> printf("Bisecting: a merge base must be tested\n");
> - exit(bisect_checkout(sha1_to_hex(mb), no_checkout));
> + exit(bisect_checkout(mb, no_checkout));
> }
> }
>
> @@ -948,7 +929,6 @@ 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 bisect_rev_hex[GIT_SHA1_HEXSZ + 1];
>
> read_bisect_terms(&term_bad, &term_good);
> if (read_bisect_refs())
> @@ -986,11 +966,10 @@ int bisect_next_all(const char *prefix, int no_checkout)
> }
>
> bisect_rev = revs.commits->item->object.sha1;
> - memcpy(bisect_rev_hex, sha1_to_hex(bisect_rev), GIT_SHA1_HEXSZ + 1);
>
> if (!hashcmp(bisect_rev, current_bad_oid->hash)) {
> exit_if_skipped_commits(tried, current_bad_oid);
> - printf("%s is the first %s commit\n", bisect_rev_hex,
> + printf("%s is the first %s commit\n", sha1_to_hex(bisect_rev),
> term_bad);
> show_diff_tree(prefix, revs.commits->item);
> /* This means the bisection process succeeded. */
> @@ -1003,7 +982,7 @@ int bisect_next_all(const char *prefix, int no_checkout)
> "(roughly %d step%s)\n", nr, (nr == 1 ? "" : "s"),
> steps, (steps == 1 ? "" : "s"));
>
> - return bisect_checkout(bisect_rev_hex, no_checkout);
> + return bisect_checkout(bisect_rev, no_checkout);
> }
>
> static inline int log2i(int n)
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 4/5] rebase: use update_ref
2015-07-28 18:18 ` Junio C Hamano
@ 2015-07-28 18:53 ` David Turner
0 siblings, 0 replies; 11+ messages in thread
From: David Turner @ 2015-07-28 18:53 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, mhagger, sunshine, philipoakley
On Tue, 2015-07-28 at 11:18 -0700, Junio C Hamano wrote:
> David Turner <dturner@twopensource.com> writes:
>
> > Instead of manually writing a pseudoref (in one case) and shelling out
> > to git update-ref (in another), use the update_ref function. This
> > is much simpler.
> >
> > Signed-off-by: David Turner <dturner@twopensource.com>
> > ---
> > bisect.c | 37 ++++++++-----------------------------
> > 1 file changed, 8 insertions(+), 29 deletions(-)
>
> Mistitled? I can do s/rebase/bisect/ at my end if that is all
> needed.
Apparently, yes. Thanks.
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 5/5] sequencer: replace write_cherry_pick_head with update_ref
2015-07-27 20:08 [PATCH v2 0/5] pseudorefs David Turner
` (3 preceding siblings ...)
2015-07-27 20:08 ` [PATCH 4/5] rebase: use update_ref David Turner
@ 2015-07-27 20:08 ` David Turner
2015-07-27 22:04 ` [PATCH v2 0/5] pseudorefs Junio C Hamano
5 siblings, 0 replies; 11+ messages in thread
From: David Turner @ 2015-07-27 20:08 UTC (permalink / raw)
To: git, mhagger, sunshine, philipoakley; +Cc: David Turner
Now update_ref (via write_pseudoref) does almost exactly what
write_cherry_pick_head did, so we can remove write_cherry_pick_head
and just use update_ref.
Signed-off-by: David Turner <dturner@twopensource.com>
---
sequencer.c | 23 ++++-------------------
1 file changed, 4 insertions(+), 19 deletions(-)
diff --git a/sequencer.c b/sequencer.c
index c4f4b7d..554a704 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -158,23 +158,6 @@ static void free_message(struct commit *commit, struct commit_message *msg)
unuse_commit_buffer(commit, msg->message);
}
-static void write_cherry_pick_head(struct commit *commit, const char *pseudoref)
-{
- const char *filename;
- int fd;
- struct strbuf buf = STRBUF_INIT;
-
- strbuf_addf(&buf, "%s\n", sha1_to_hex(commit->object.sha1));
-
- filename = git_path("%s", pseudoref);
- fd = open(filename, O_WRONLY | O_CREAT, 0666);
- if (fd < 0)
- die_errno(_("Could not open '%s' for writing"), filename);
- if (write_in_full(fd, buf.buf, buf.len) != buf.len || close(fd))
- die_errno(_("Could not write to '%s'"), filename);
- strbuf_release(&buf);
-}
-
static void print_advice(int show_hint, struct replay_opts *opts)
{
char *msg = getenv("GIT_CHERRY_PICK_HELP");
@@ -607,9 +590,11 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
* write it at all.
*/
if (opts->action == REPLAY_PICK && !opts->no_commit && (res == 0 || res == 1))
- write_cherry_pick_head(commit, "CHERRY_PICK_HEAD");
+ update_ref(NULL, "CHERRY_PICK_HEAD", commit->object.sha1, NULL,
+ REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);
if (opts->action == REPLAY_REVERT && ((opts->no_commit && res == 0) || res == 1))
- write_cherry_pick_head(commit, "REVERT_HEAD");
+ update_ref(NULL, "REVERT_HEAD", commit->object.sha1, NULL,
+ REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);
if (res) {
error(opts->action == REPLAY_REVERT
--
2.0.4.315.gad8727a-twtrsrc
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v2 0/5] pseudorefs
2015-07-27 20:08 [PATCH v2 0/5] pseudorefs David Turner
` (4 preceding siblings ...)
2015-07-27 20:08 ` [PATCH 5/5] sequencer: replace write_cherry_pick_head with update_ref David Turner
@ 2015-07-27 22:04 ` Junio C Hamano
5 siblings, 0 replies; 11+ messages in thread
From: Junio C Hamano @ 2015-07-27 22:04 UTC (permalink / raw)
To: David Turner; +Cc: git, mhagger, sunshine, philipoakley
David Turner <dturner@twopensource.com> writes:
> This version of the pseudorefs patch series is much simpler. Instead
> of forbidding update_ref and delete_ref from updating pseudorefs,
> these functions now just special-case pseudorefs. So we can use
> update_ref to write pseudorefs in a rebase and sequencer, and
> we don't need to rewrite so much code.
The resulting update_ref/delete_ref look quite straight-forward,
too. Thanks.
> In addition, I made typo fixes suggested by Eric Sunshine and Philip
> Oakley.
^ permalink raw reply [flat|nested] 11+ messages in thread