* [PATCH] Add -S, --gpg-sign option to manpage of "git commit"
From: Tom Jones @ 2012-10-21 19:46 UTC (permalink / raw)
To: git; +Cc: tom
git commit -S, --gpg-sign was mentioned in the program's help message,
but not in the manpage.
This adds an equivalent entry for the option in the manpage.
---
Documentation/git-commit.txt | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index 9594ac8..0e0a22c 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -13,7 +13,7 @@ SYNOPSIS
[-F <file> | -m <msg>] [--reset-author] [--allow-empty]
[--allow-empty-message] [--no-verify] [-e] [--author=<author>]
[--date=<date>] [--cleanup=<mode>] [--status | --no-status]
- [-i | -o] [--] [<file>...]
+ [-i | -o] [--] [-S[keyid]] [<file>...]
DESCRIPTION
-----------
@@ -276,6 +276,10 @@ configuration variable documented in linkgit:git-config[1].
commit message template when using an editor to prepare the
default commit message.
+-S[<keyid>]::
+--gpg-sign[=<keyid>]::
+ GPG-sign commit.
+
\--::
Do not interpret any more arguments as options.
--
1.7.2.5
^ permalink raw reply related
* Re: Subtree in Git
From: Junio C Hamano @ 2012-10-21 19:51 UTC (permalink / raw)
To: Herman van Rink; +Cc: dag, greened, Hilco Wijbenga, Git Users
In-Reply-To: <5084102A.2010006@initfour.nl>
Herman van Rink <rink@initfour.nl> writes:
> On 10/21/2012 08:32 AM, Junio C Hamano wrote:
>> Herman van Rink <rink@initfour.nl> writes:
>>
>>> Junio, Could you please consider merging the single commit from my
>>> subtree-updates branch? https://github.com/helmo/git/tree/subtree-updates
>> In general, in areas like contrib/ where there is a volunteer area
>> maintainer, unless the change something ultra-urgent (e.g. serious
>> security fix) and the area maintainer is unavailable, I'm really
>> reluctant to bypass and take a single patch that adds many things
>> that are independent from each other.
>
> Who do you see as volunteer area maintainer for contrib/subtree?
> My best guess would be Dave. And he already indicated earlier in the
> thread to be ok with the combined patch as long as you are ok with it.
Yes, dag volunteered to be the area maintainer to act as a
gatekeeper for me.
The message you addressed to me was sent as a response to his
message, where he gave you specific suggestions to improve the patch
and turn it into a readable series instead of a single ball of wax
and it looked to me as if you are trying to bypass him and shove the
single ball of wax to our history over his objection.
I haven't formed an opinion on the particular change as to how bad
its collapsing unrelated changes into a single change is. Maybe they
are not as unrelated and form a coherent whole. Maybe not. Also I
personally do not mind too much if the area maintainer for contrib/
has a lower standard for atomicity of commits compared to the rest
of the system. But I do prefer the decision to be made at the level
of area maintainer's, and have issues when people try to bypass
without a good reason.
Note that I was not following the thread very closely, so I may have
misread the discussion. I read his "Unless Junio accepts..." to
mean "I (dag) still object, but if Junio accepts that patch I object
to directly, there is nothing I can do about it". That is very
different from "I am on the fence and cannot decide it is a good
patch or not. I'll let Junio decide; I am OK as long as he is".
Thanks.
^ permalink raw reply
* Re: git fetch documentation problem or bug
From: Junio C Hamano @ 2012-10-21 19:30 UTC (permalink / raw)
To: Drew Northup
Cc: git, Angelo Borsotti, Carlos Martín Nieto, Matthieu Moy,
Nguyễn Thái Ngọc
In-Reply-To: <CAM9Z-nnKTq0C9wPA=JKZ3qzTmL3NVisfy=rbjjq1yKEVrN53FQ@mail.gmail.com>
Drew Northup <n1xim.email@gmail.com> writes:
> On Mon, Oct 8, 2012 at 7:33 PM, Junio C Hamano <gitster@pobox.com> wrote:
>> Junio C Hamano <gitster@pobox.com> writes:
>>
>> I personally do not think the downside of breaking backward
>> compatibility is too bad. If we do this only when we already are
>> configured to keep remote tracking branch for branch $branch from
>> remote $from (it has to be given as a nickname, not URL that happens
>> to have an entry in the configuration), then a promiscuous fetch
>> that grabs from a URL (or a nickname that is configured not to keep
>> tracking branches) will not change any behaviour, and when you want
>> to keep your remote tracking branch intact while doing one-shot
>> fetch for whatever reason, you can say "git fetch $from $branch:" to
>> explicitly decline copying.
>
> How are we supposed to remember those are different?
>
> "git fetch $from $branch..."
> VS
> "git fetch $from $branch:"
I do not know what you meant by the three dots, but you are supposed
to know what you meant by $branch... whatever it is. It is what you
wrote, not I did ;-)
Let me clarify what is in the message you are responding to.
git fetch $from $branch
(no colon in $branch part anywhere) traditionally meant a short-hand
of saying
git fetch $from $branch:
I.e. "fetch $branch and store in FETCH_HEAD but not anywhere else".
The hypothesized change is to make it a short-hand of saying
git fetch $from $branch:refs/remotes/$from/$branch
when "git fetch $from" is already configured to store the result
there.
Without [remote "$from"] fetch = refs/heads/*:refs/remotes/$from/*
configured, it will still mean "git fetch $from $branch:".
And for the record, I am *not* enthused about such a change. I am
only saying that, seeing that many new people seem to wish the
command behaved that way, such a change would not hurt existing
users too much. Switching the meaning of shorthand (i.e. a piece of
refspec that does not have any colon) from "just fetch but do not
store" from "fetch and store in the remote tracking ref if it is
configured to do so without command override" is still a backward
incompatible change.
> I strongly prefer EXPLICITLY setting tracking than expecting some
> extreme syntactic nuance to quietly do it for me now and confuse the
> heck out of me later.
This is not about your preference. This is about what happens when
you say something on the command line to override your explicit
setting you have in $GIT_DIR/config
[remote "$from"] fetch = ...
^ permalink raw reply
* [PATCH] transport-helper: check when helpers fail
From: Felipe Contreras @ 2012-10-21 19:19 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Sverre Rabbelier, Shawn O. Pearce,
Felipe Contreras
Otherwise transport-helper will continue checking for refs and other
things what will confuse the user more.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
git-remote-testgit.py | 3 +++
run-command.c | 17 +++++++++++++++++
run-command.h | 1 +
t/t5800-remote-helpers.sh | 6 ++++++
transport-helper.c | 8 ++++++++
5 files changed, 35 insertions(+)
diff --git a/git-remote-testgit.py b/git-remote-testgit.py
index 5f3ebd2..355e3f5 100644
--- a/git-remote-testgit.py
+++ b/git-remote-testgit.py
@@ -159,6 +159,9 @@ def do_import(repo, args):
ref = line[7:].strip()
refs.append(ref)
+ if os.environ.get("GIT_REMOTE_TESTGIT_FAILURE"):
+ die('Told to fail')
+
repo = update_local_repo(repo)
repo.exporter.export_repo(repo.gitdir, refs)
diff --git a/run-command.c b/run-command.c
index 1101ef7..2852e9d 100644
--- a/run-command.c
+++ b/run-command.c
@@ -559,6 +559,23 @@ int run_command(struct child_process *cmd)
return finish_command(cmd);
}
+int check_command(struct child_process *cmd)
+{
+ int status;
+ pid_t pid;
+
+ pid = waitpid(cmd->pid, &status, WNOHANG);
+
+ if (pid < 0)
+ return -1;
+ if (WIFSIGNALED(status))
+ return WTERMSIG(status);
+ if (WIFEXITED(status))
+ return WEXITSTATUS(status);
+
+ return 0;
+}
+
static void prepare_run_command_v_opt(struct child_process *cmd,
const char **argv,
int opt)
diff --git a/run-command.h b/run-command.h
index 44f7d2b..9019e38 100644
--- a/run-command.h
+++ b/run-command.h
@@ -45,6 +45,7 @@ struct child_process {
int start_command(struct child_process *);
int finish_command(struct child_process *);
int run_command(struct child_process *);
+int check_command(struct child_process *cmd);
extern int run_hook(const char *index_file, const char *name, ...);
diff --git a/t/t5800-remote-helpers.sh b/t/t5800-remote-helpers.sh
index e7dc668..d4b17ae 100755
--- a/t/t5800-remote-helpers.sh
+++ b/t/t5800-remote-helpers.sh
@@ -145,4 +145,10 @@ test_expect_failure 'push new branch with old:new refspec' '
compare_refs clone HEAD server refs/heads/new-refspec
'
+test_expect_success 'proper failure checks' '
+ export GIT_REMOTE_TESTGIT_FAILURE=1 &&
+ ! git clone "testgit::$PWD/server" failure 2> errors &&
+ grep -q "Error while running helper" errors
+'
+
test_done
diff --git a/transport-helper.c b/transport-helper.c
index cfe0988..fbd923d 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -441,6 +441,10 @@ static int fetch_with_import(struct transport *transport,
if (finish_command(&fastimport))
die("Error while running fast-import");
+
+ if (check_command(data->helper))
+ die("Error while running helper");
+
free(fastimport.argv);
fastimport.argv = NULL;
@@ -784,6 +788,10 @@ static int push_refs_with_export(struct transport *transport,
if (finish_command(&exporter))
die("Error while running fast-export");
+
+ if (check_command(data->helper))
+ die("Error while running helper");
+
push_update_refs_status(data, remote_refs);
return 0;
}
--
1.8.0.rc2
^ permalink raw reply related
* Re: [RFC/PATCH] git symbolic-ref --delete $symref
From: Junio C Hamano @ 2012-10-21 19:16 UTC (permalink / raw)
To: Johan Herland; +Cc: git
In-Reply-To: <1350819153-23491-1-git-send-email-johan@herland.net>
Johan Herland <johan@herland.net> writes:
> Teach symbolic-ref to delete symrefs by adding the -d/--delete option to
> git-symbolic-ref. Both proper and dangling symrefs are deleted by this
> option, but other refs - or anything else that is not a symref - is not.
>
> The symref deletion is performed by first verifying that we are given a
> proper symref, and then invoking delete_ref() on it with the REF_NODEREF
> flag.
>
> Signed-off-by: Johan Herland <johan@herland.net>
> ---
>
> Here is a quick first attempt at implementing the 'git symbolic-ref -d'
> you've been mentioning in the symref deletion thread.
Existing users are used to 'update-ref -d --no-deref SYM' being the
way to delete a symref (even though 'symbolic-ref SYM' being the way
to create one), I think, and the lack of this option in symbolic-ref
would not have hurt them, and addition of this option wouldn't help
them very much, either.
But addition of this option would help new people who wonder, after
creating a symref with 'symbolic-ref' (perhaps with a wrong name),
what command is to be used to remove it, finding no removal option
in the same command.
Thanks.
> Documentation/git-symbolic-ref.txt | 10 +++++++++-
> builtin/symbolic-ref.c | 33 +++++++++++++++++++++++----------
> t/t1401-symbolic-ref.sh | 30 ++++++++++++++++++++++++++++++
> 3 files changed, 62 insertions(+), 11 deletions(-)
>
> diff --git a/Documentation/git-symbolic-ref.txt b/Documentation/git-symbolic-ref.txt
> index 981d3a8..ef68ad2 100644
> --- a/Documentation/git-symbolic-ref.txt
> +++ b/Documentation/git-symbolic-ref.txt
> @@ -3,13 +3,14 @@ git-symbolic-ref(1)
>
> NAME
> ----
> -git-symbolic-ref - Read and modify symbolic refs
> +git-symbolic-ref - Read, modify and delete symbolic refs
>
> SYNOPSIS
> --------
> [verse]
> 'git symbolic-ref' [-m <reason>] <name> <ref>
> 'git symbolic-ref' [-q] [--short] <name>
> +'git symbolic-ref' --delete [-q] <name>
>
> DESCRIPTION
> -----------
> @@ -21,6 +22,9 @@ argument to see which branch your working tree is on.
> Given two arguments, creates or updates a symbolic ref <name> to
> point at the given branch <ref>.
>
> +Given `--delete` and an additional argument, deletes the given
> +symbolic ref.
> +
> A symbolic ref is a regular file that stores a string that
> begins with `ref: refs/`. For example, your `.git/HEAD` is
> a regular file whose contents is `ref: refs/heads/master`.
> @@ -28,6 +32,10 @@ a regular file whose contents is `ref: refs/heads/master`.
> OPTIONS
> -------
>
> +-d::
> +--delete::
> + Delete the symbolic ref <name>.
> +
> -q::
> --quiet::
> Do not issue an error message if the <name> is not a
> diff --git a/builtin/symbolic-ref.c b/builtin/symbolic-ref.c
> index 9e92828..f481959 100644
> --- a/builtin/symbolic-ref.c
> +++ b/builtin/symbolic-ref.c
> @@ -5,12 +5,11 @@
>
> static const char * const git_symbolic_ref_usage[] = {
> N_("git symbolic-ref [options] name [ref]"),
> + N_("git symbolic-ref -d [-q] name"),
> NULL
> };
>
> -static int shorten;
> -
> -static void check_symref(const char *HEAD, int quiet)
> +static int check_symref(const char *HEAD, int quiet, int shorten, int print)
> {
> unsigned char sha1[20];
> int flag;
> @@ -22,20 +21,24 @@ static void check_symref(const char *HEAD, int quiet)
> if (!quiet)
> die("ref %s is not a symbolic ref", HEAD);
> else
> - exit(1);
> + return 1;
> + }
> + if (print) {
> + if (shorten)
> + refname = shorten_unambiguous_ref(refname, 0);
> + puts(refname);
> }
> - if (shorten)
> - refname = shorten_unambiguous_ref(refname, 0);
> - puts(refname);
> + return 0;
> }
>
> int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
> {
> - int quiet = 0;
> + int quiet = 0, delete = 0, shorten = 0, ret = 0;
> const char *msg = NULL;
> struct option options[] = {
> OPT__QUIET(&quiet,
> N_("suppress error message for non-symbolic (detached) refs")),
> + OPT_BOOL('d', "delete", &delete, N_("delete symbolic ref")),
> OPT_BOOL(0, "short", &shorten, N_("shorten ref output")),
> OPT_STRING('m', NULL, &msg, N_("reason"), N_("reason of the update")),
> OPT_END(),
> @@ -46,9 +49,19 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
> git_symbolic_ref_usage, 0);
> if (msg &&!*msg)
> die("Refusing to perform update with empty message");
> +
> + if (delete) {
> + if (argc != 1)
> + usage_with_options(git_symbolic_ref_usage, options);
> + ret = check_symref(argv[0], 1, 0, 0);
> + if (ret)
> + die("Cannot delete %s, not a symbolic ref", argv[0]);
> + return delete_ref(argv[0], NULL, REF_NODEREF);
> + }
> +
> switch (argc) {
> case 1:
> - check_symref(argv[0], quiet);
> + ret = check_symref(argv[0], quiet, shorten, 1);
> break;
> case 2:
> if (!strcmp(argv[0], "HEAD") &&
> @@ -59,5 +72,5 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
> default:
> usage_with_options(git_symbolic_ref_usage, options);
> }
> - return 0;
> + return ret;
> }
> diff --git a/t/t1401-symbolic-ref.sh b/t/t1401-symbolic-ref.sh
> index 2c96551..36378b0 100755
> --- a/t/t1401-symbolic-ref.sh
> +++ b/t/t1401-symbolic-ref.sh
> @@ -33,4 +33,34 @@ test_expect_success 'symbolic-ref refuses bare sha1' '
> '
> reset_to_sane
>
> +test_expect_success 'symbolic-ref deletes HEAD' '
> + git symbolic-ref -d HEAD &&
> + test_path_is_file .git/refs/heads/foo &&
> + test_path_is_missing .git/HEAD
> +'
> +reset_to_sane
> +
> +test_expect_success 'symbolic-ref deletes dangling HEAD' '
> + git symbolic-ref HEAD refs/heads/missing &&
> + git symbolic-ref -d HEAD &&
> + test_path_is_missing .git/refs/heads/missing &&
> + test_path_is_missing .git/HEAD
> +'
> +reset_to_sane
> +
> +test_expect_success 'symbolic-ref fails to delete missing FOO' '
> + echo "fatal: Cannot delete FOO, not a symbolic ref" >expect &&
> + test_must_fail git symbolic-ref -d FOO >actual 2>&1 &&
> + test_cmp expect actual
> +'
> +reset_to_sane
> +
> +test_expect_success 'symbolic-ref fails to delete real ref' '
> + echo "fatal: Cannot delete refs/heads/foo, not a symbolic ref" >expect &&
> + test_must_fail git symbolic-ref -d refs/heads/foo >actual 2>&1 &&
> + test_path_is_file .git/refs/heads/foo &&
> + test_cmp expect actual
> +'
> +reset_to_sane
> +
> test_done
> --
> 1.7.12.1.609.g5cd6968
^ permalink raw reply
* Re: [PATCH 2/2] Fix failure to delete a packed ref through a symref
From: Junio C Hamano @ 2012-10-21 19:09 UTC (permalink / raw)
To: Johan Herland; +Cc: git, rene.scharfe, vmiklos
In-Reply-To: <1350816032-16312-3-git-send-email-johan@herland.net>
Johan Herland <johan@herland.net> writes:
> When deleting a ref through a symref (e.g. using 'git update-ref -d HEAD'
> to delete refs/heads/master), we would remove the loose ref, but a packed
> version of the same ref would remain, the end result being that instead of
> deleting refs/heads/master we would appear to reset it to its state as of
> the last repack.
>
> This patch fixes the issue, by making sure we pass the correct ref name
> when invoking repack_without_ref() from within delete_ref().
>
> Signed-off-by: Johan Herland <johan@herland.net>
> ---
Thanks. Will queue.
> refs.c | 2 +-
> t/t1400-update-ref.sh | 2 +-
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/refs.c b/refs.c
> index 726c53c..6cec1c8 100644
> --- a/refs.c
> +++ b/refs.c
> @@ -1779,7 +1779,7 @@ int delete_ref(const char *refname, const unsigned char *sha1, int delopt)
> * packed one. Also, if it was not loose we need to repack
> * without it.
> */
> - ret |= repack_without_ref(refname);
> + ret |= repack_without_ref(lock->ref_name);
>
> unlink_or_warn(git_path("logs/%s", lock->ref_name));
> invalidate_ref_cache(NULL);
> diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
> index f7ec203..e415ee0 100755
> --- a/t/t1400-update-ref.sh
> +++ b/t/t1400-update-ref.sh
> @@ -85,7 +85,7 @@ test_expect_success \
> "move $m (by HEAD)" \
> "git update-ref HEAD $B $A &&
> test $B"' = $(cat .git/'"$m"')'
> -test_expect_failure "delete $m (by HEAD) should remove both packed and loose $m" '
> +test_expect_success "delete $m (by HEAD) should remove both packed and loose $m" '
> git update-ref -d HEAD $B &&
> ! grep "$m" .git/packed-refs &&
> ! test -f .git/$m
^ permalink raw reply
* Re: [PATCH] Fix git p4 sync errors
From: Junio C Hamano @ 2012-10-21 19:06 UTC (permalink / raw)
To: Matt Arsenault; +Cc: git, Pete Wyckoff, Luke Diamand
In-Reply-To: <AC43C2B4-623F-4590-9F92-6CCA26645EFE@gmail.com>
[Added area experts of git-p4 to Cc.]
Matt Arsenault <arsenm2@gmail.com> writes:
> From 425e4dc6992d07aa00039c5bb8e8c76def591fd3 Mon Sep 17 00:00:00 2001
> From: Matt Arsenault <arsenm2@gmail.com>
> Date: Sat, 20 Oct 2012 18:48:45 -0700
> Subject: [PATCH] git-p4: Fix not using -s option to describe
Please do not include these four lines in the body of the message.
The "Subject: " line is there so that you can copy & paste to your
MUA (instead of having to type something different from scratch),
and we use the authorship From/Date from your e-mail message.
>
> This solves errors in some cases when syncing renamed files.
Can you be a bit more descriptive? What are "errors in some case"?
A good rule of thumb is to imagine a user of this command who is
having a problem who reads this commit log message. Does the
symptom described to have fixed by the commit detailed enough to
allow her to tell if this change may potentially fix the problem she
is having?
> Other places where describe is used use the -s, except this one.
This makes it sound as if the changed line was an odd-man out among
many others, and it is clear we always want "describe -s" throughout
this command. But my "git grep 'p4.*describe'" shows there are two
places, one with "-s" and one without.
What are returned from this invocation of p4Cmd() seem to be passed
to self.splitFilesIntoBranches() as its commit[] and the fields
'depotFile#', 'rev#', 'action#' and 'type#' are looked at in the
method, and then to self.commit() as its details[], for fields
'time', 'user', 'change', 'desc', and 'options'.
What field, if any, gets wrong value when "-s" is not used? Or
perhaps some fields are omitted incorrectly? What field are we
getting out of p4Cmd() that we are not using in the existing
callchain by not passing "-s" [*1*]?
In short, what I am getting at are:
- What breaks by not passing "-s"? What are the user visible
symptoms?
- Why is it a bug not to pass "-s"? How does the bug happen?
Thanks.
[footnote]
*1*
http://www.perforce.com/perforce/r12.1/manuals/cmdref/describe.html
says that "describe -s" omits files diffs, but I do not know how it
affects "-G describe -s" output that we are reading (what fields in
the unmarshalled dict we are reading from is affected).
> Signed-off-by: Matt Arsenault <arsenm2@gmail.com>
> ---
> git-p4.py | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/git-p4.py b/git-p4.py
> index 882b1bb..e203508 100755
> --- a/git-p4.py
> +++ b/git-p4.py
> @@ -2543,7 +2543,7 @@ class P4Sync(Command, P4UserMap):
> def importChanges(self, changes):
> cnt = 1
> for change in changes:
> - description = p4Cmd(["describe", str(change)])
> + description = p4Cmd(["describe", "-s", str(change)])
> self.updateOptionDict(description)
>
> if not self.silent:
^ permalink raw reply
* Re: [PATCH] Add new git-remote-hd helper
From: Felipe Contreras @ 2012-10-21 18:03 UTC (permalink / raw)
To: Johannes Schindelin
Cc: Sverre Rabbelier, git, Junio C Hamano, Ilari Liusvaara,
Daniel Barkalow
In-Reply-To: <alpine.DEB.1.00.1210181031320.3049@bonsai2>
On Thu, Oct 18, 2012 at 10:47 AM, Johannes Schindelin
<Johannes.Schindelin@gmx.de> wrote:
> Without push support, remote-hg is useless to me. Without regression tests
> proving that it is rock solid, I will not use remote-hg.
Done and done. My remote-hg now has support for pushing, all in less
than 500 lines of code. It also manages to pass all 14 of the
"extensive tests" of your remote-hg. Anything else?
--
Felipe Contreras
^ permalink raw reply
* [PATCH v3 6/6] tests: fix remote-hg warnings for modern git
From: Felipe Contreras @ 2012-10-21 17:49 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Sverre Rabbelier, Johannes Schindelin,
Ilari Liusvaara, Daniel Barkalow, Jeff King, Michael J Gruber,
Felipe Contreras
In-Reply-To: <1350841744-21564-1-git-send-email-felipe.contreras@gmail.com>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
t/t5801-remote-hg.sh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/t/t5801-remote-hg.sh b/t/t5801-remote-hg.sh
index 2e68372..ba4d7a2 100755
--- a/t/t5801-remote-hg.sh
+++ b/t/t5801-remote-hg.sh
@@ -95,7 +95,7 @@ test_expect_success 'pushing to local repo' '
(cd localclone &&
echo content >>file &&
git commit -a -m three &&
- git push) &&
+ git push --all) &&
(cd server &&
hg up tip) &&
vcs_cmp localclone server
@@ -110,7 +110,7 @@ test_expect_success 'pushing remote local repo' '
(cd clone &&
echo content >>file &&
git commit -a -m four &&
- git push) &&
+ git push --all) &&
(cd server &&
hg up tip) &&
vcs_cmp clone server
--
1.8.0.rc2.7.g0961fdf.dirty
^ permalink raw reply related
* [PATCH v3 5/6] tests: add remote-hg tests
From: Felipe Contreras @ 2012-10-21 17:49 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Sverre Rabbelier, Johannes Schindelin,
Ilari Liusvaara, Daniel Barkalow, Jeff King, Michael J Gruber,
Felipe Contreras
In-Reply-To: <1350841744-21564-1-git-send-email-felipe.contreras@gmail.com>
>From the original remote-hg.
You need git-remote-hg already in your path to run them.
I'm not proposing to include this patch like this, but should make it easier to
test.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
t/t5801-remote-hg.sh | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 143 insertions(+)
create mode 100755 t/t5801-remote-hg.sh
diff --git a/t/t5801-remote-hg.sh b/t/t5801-remote-hg.sh
new file mode 100755
index 0000000..2e68372
--- /dev/null
+++ b/t/t5801-remote-hg.sh
@@ -0,0 +1,143 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Sverre Rabbelier
+#
+
+test_description='Test remote-helper import and export commands'
+
+. ./test-lib.sh
+
+if test_have_prereq PYTHON && "$PYTHON_PATH" -c '
+import sys
+if sys.hexversion < 0x02040000:
+ sys.exit(1)
+'
+then
+ :
+else
+ skip_all='skipping git remote-hg tests: requires Python 2.4 or newer'
+ test_done
+fi
+
+if ! type hg >/dev/null 2>&1
+then
+ skip_all='skipping git remote-hg tests: requires hg'
+ test_done
+fi
+
+# Call cmp with the arguments -x ".hg" -x ".git" <left> <right>
+
+vcs_cmp () {
+ $DIFF -u -x ".hg" -x ".git" $1 $2
+}
+
+ROOT=$PWD
+
+test_expect_success 'setup repository' '
+ printf "[ui]\nusername = A U Thor <author@example.com>" > \
+ ${HOME}/.hgrc &&
+ mkdir server &&
+ hg init server/.hg &&
+ hg clone "$ROOT/server" public &&
+ (cd public &&
+ echo content >file &&
+ hg add file &&
+ hg commit -m one &&
+ hg push)
+'
+
+test_expect_success 'cloning from local repo' '
+ git clone "hg::file://${ROOT}/server" localclone &&
+ vcs_cmp public localclone
+'
+
+test_expect_success 'cloning from remote repo' '
+ git clone "hg::remote://${ROOT}/server" clone &&
+ vcs_cmp public clone
+'
+
+test_expect_success 'create new commit on remote' '
+ (cd public &&
+ echo content >>file &&
+ hg commit -A -m two &&
+ hg push)
+'
+
+test_expect_success 'pulling from local repo' '
+ (cd localclone && git pull) &&
+ vcs_cmp public localclone
+'
+
+test_expect_success 'pulling from remote remote' '
+ (cd clone && git pull) &&
+ vcs_cmp public clone
+'
+
+test_expect_success 'pushing to local empty repo' '
+ hg init localempty &&
+ (cd localclone &&
+ git push --all "hg::file://${ROOT}/localempty") &&
+ (cd localempty &&
+ hg up tip) &&
+ vcs_cmp localclone localempty
+'
+
+test_expect_success 'pushing to remote empty repo' '
+ hg init empty &&
+ (cd localclone &&
+ git push --all "hg::remote://${ROOT}/empty") &&
+ (cd empty &&
+ hg up tip) &&
+ vcs_cmp localclone empty
+'
+
+test_expect_success 'pushing to local repo' '
+ (cd localclone &&
+ echo content >>file &&
+ git commit -a -m three &&
+ git push) &&
+ (cd server &&
+ hg up tip) &&
+ vcs_cmp localclone server
+'
+
+test_expect_success 'synch with changes from localclone' '
+ (cd clone &&
+ git pull)
+'
+
+test_expect_success 'pushing remote local repo' '
+ (cd clone &&
+ echo content >>file &&
+ git commit -a -m four &&
+ git push) &&
+ (cd server &&
+ hg up tip) &&
+ vcs_cmp clone server
+'
+
+test_expect_success 'creating new branch' '
+ (cd public &&
+ hg branch different-branch &&
+ echo different >> file &&
+ hg commit -m five &&
+ hg push -f)
+'
+
+test_expect_success 'pull in new branch to local repository' '
+ (cd localclone &&
+ git fetch origin default &&
+ test_must_fail git rev-parse -q --verify refs/remotes/origin/different-branch &&
+ git fetch &&
+ git rev-parse --no-revs --verify refs/remotes/origin/different-branch)
+'
+
+test_expect_success 'pull in new branch to remote repository' '
+ (cd clone &&
+ git fetch origin default &&
+ test_must_fail git rev-parse -q --verify refs/remotes/origin/different-branch &&
+ git fetch &&
+ git rev-parse --no-revs --verify refs/remotes/origin/different-branch)
+'
+
+test_done
--
1.8.0.rc2.7.g0961fdf.dirty
^ permalink raw reply related
* [PATCH v3 4/6] remote-hg: add support for trivial features
From: Felipe Contreras @ 2012-10-21 17:49 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Sverre Rabbelier, Johannes Schindelin,
Ilari Liusvaara, Daniel Barkalow, Jeff King, Michael J Gruber,
Felipe Contreras
In-Reply-To: <1350841744-21564-1-git-send-email-felipe.contreras@gmail.com>
So that the other remote-hg tests don't barf.
I'm not particularily happy with this code, but does the trick.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
contrib/remote-hg/git-remote-hg | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/contrib/remote-hg/git-remote-hg b/contrib/remote-hg/git-remote-hg
index 34a00cd..772bb69 100755
--- a/contrib/remote-hg/git-remote-hg
+++ b/contrib/remote-hg/git-remote-hg
@@ -12,6 +12,7 @@ import re
import sys
import os
import json
+import shutil
first = True
@@ -172,7 +173,13 @@ def get_repo(url, alias):
myui = ui.ui()
myui.setconfig('ui', 'interactive', 'off')
- if hg.islocal(url):
+ if url.startswith("remote://"):
+ remote = True
+ url = "file://%s" % url[9:]
+ else:
+ remote = False
+
+ if hg.islocal(url) and not remote:
repo = hg.repository(myui, url)
else:
local_path = os.path.join(dirname, 'clone')
@@ -442,6 +449,12 @@ def main(args):
url = args[2]
peer = None
+ if not alias.isalnum():
+ is_tmp = True
+ alias = "tmp"
+ else:
+ is_tmp = False
+
gitdir = os.environ['GIT_DIR']
dirname = os.path.join(gitdir, 'hg', alias)
branches = {}
@@ -468,6 +481,9 @@ def main(args):
do_export(parser)
sys.stdout.flush()
- marks.store()
+ if not is_tmp:
+ marks.store()
+ else:
+ shutil.rmtree(dirname)
sys.exit(main(sys.argv))
--
1.8.0.rc2.7.g0961fdf.dirty
^ permalink raw reply related
* [PATCH v3 3/6] remote-hg: add support for remote pushing
From: Felipe Contreras @ 2012-10-21 17:49 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Sverre Rabbelier, Johannes Schindelin,
Ilari Liusvaara, Daniel Barkalow, Jeff King, Michael J Gruber,
Felipe Contreras
In-Reply-To: <1350841744-21564-1-git-send-email-felipe.contreras@gmail.com>
I'm not happy with this, but works.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
contrib/remote-hg/git-remote-hg | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/contrib/remote-hg/git-remote-hg b/contrib/remote-hg/git-remote-hg
index fc4510c..34a00cd 100755
--- a/contrib/remote-hg/git-remote-hg
+++ b/contrib/remote-hg/git-remote-hg
@@ -167,6 +167,7 @@ def fixup_user(user):
def get_repo(url, alias):
global dirname
+ global peer
myui = ui.ui()
myui.setconfig('ui', 'interactive', 'off')
@@ -176,7 +177,7 @@ def get_repo(url, alias):
else:
local_path = os.path.join(dirname, 'clone')
if not os.path.exists(local_path):
- srcpeer, dstpeer = hg.clone(myui, {}, url, local_path, update=False, pull=True)
+ peer, dstpeer = hg.clone(myui, {}, url, local_path, update=False, pull=True)
repo = dstpeer.local()
else:
repo = hg.repository(myui, local_path)
@@ -420,6 +421,8 @@ def parse_commit(parser):
print "ok %s" % ref
def do_export(parser):
+ global peer
+
for line in parser.each_block('done'):
if parser.check('blob'):
parse_blob(parser)
@@ -427,12 +430,17 @@ def do_export(parser):
parse_commit(parser)
print
+ if peer:
+ parser.repo.push(peer, force=False)
+
def main(args):
global prefix, dirname, branches
global marks, blob_marks
+ global peer
alias = args[1]
url = args[2]
+ peer = None
gitdir = os.environ['GIT_DIR']
dirname = os.path.join(gitdir, 'hg', alias)
--
1.8.0.rc2.7.g0961fdf.dirty
^ permalink raw reply related
* [PATCH v3 2/6] remote-hg: add support for pushing
From: Felipe Contreras @ 2012-10-21 17:49 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Sverre Rabbelier, Johannes Schindelin,
Ilari Liusvaara, Daniel Barkalow, Jeff King, Michael J Gruber,
Felipe Contreras
In-Reply-To: <1350841744-21564-1-git-send-email-felipe.contreras@gmail.com>
Some parsing of fast-export parsing might be missing, but I couldn't find any.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
contrib/remote-hg/git-remote-hg | 156 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 154 insertions(+), 2 deletions(-)
diff --git a/contrib/remote-hg/git-remote-hg b/contrib/remote-hg/git-remote-hg
index f0ce4a4..fc4510c 100755
--- a/contrib/remote-hg/git-remote-hg
+++ b/contrib/remote-hg/git-remote-hg
@@ -6,7 +6,7 @@
# Then you can clone with:
# git clone hg::/path/to/mercurial/repo/
-from mercurial import hg, ui
+from mercurial import hg, ui, context
import re
import sys
@@ -16,6 +16,7 @@ import json
first = True
AUTHOR_RE = re.compile('^((.+?) )?(<.+?>)$')
+RAW_AUTHOR_RE = re.compile('^(\w+) (.+) <(.+)> (\d+) ([+-]\d+)')
def die(msg, *args):
sys.stderr.write('ERROR: %s\n' % (msg % args))
@@ -27,12 +28,17 @@ def warn(msg, *args):
def gitmode(flags):
return 'l' in flags and '120000' or 'x' in flags and '100755' or '100644'
+def hgmode(mode):
+ m = { '0100755': 'x', '0120000': 'l' }
+ return m.get(mode, '')
+
class Marks:
def __init__(self, path):
self.path = path
self.tips = {}
self.marks = {}
+ self.rev_hgmarks = {}
self.last_mark = 0
self.load()
@@ -47,6 +53,9 @@ class Marks:
self.marks = tmp['marks']
self.last_mark = tmp['last-mark']
+ for rev, mark in self.marks.iteritems():
+ self.rev_hgmarks[mark] = int(rev)
+
def dict(self):
return { 'tips': self.tips, 'marks': self.marks, 'last-mark' : self.last_mark }
@@ -59,11 +68,19 @@ class Marks:
def from_rev(self, rev):
return self.marks[str(rev)]
+ def to_rev(self, mark):
+ return self.rev_hgmarks[mark]
+
def next_mark(self, rev):
self.last_mark += 1
self.marks[str(rev)] = self.last_mark
return self.last_mark
+ def new_mark(self, rev, mark):
+ self.marks[str(rev)] = mark
+ self.rev_hgmarks[mark] = rev
+ self.last_mark = mark
+
def is_marked(self, rev):
return self.marks.has_key(str(rev))
@@ -96,6 +113,28 @@ class Parser:
def __iter__(self):
return self.each_block('')
+ def next(self):
+ self.line = self.get_line()
+ if self.line == 'done':
+ self.line = None
+
+ def get_mark(self):
+ i = self.line.index(':') + 1
+ return int(self.line[i:])
+
+ def get_data(self):
+ if not self.check('data'):
+ return None
+ i = self.line.index(' ') + 1
+ size = int(self.line[i:])
+ return sys.stdin.read(size)
+
+ def get_author(self):
+ m = RAW_AUTHOR_RE.match(self.line)
+ if not m:
+ return None
+ return list(m.groups())[1:]
+
def export_file(fc):
if fc.path() == '.hgtags':
return
@@ -150,6 +189,10 @@ def rev_to_mark(rev):
global marks
return marks.from_rev(rev)
+def mark_to_rev(mark):
+ global marks
+ return marks.to_rev(mark)
+
def export_tag(repo, tag):
global prefix
print "reset %s/tags/%s" % (prefix, tag)
@@ -229,8 +272,16 @@ def do_capabilities(parser):
global prefix, dirname
print "import"
+ print "export"
print "refspec refs/heads/*:%s/branches/*" % prefix
print "refspec refs/tags/*:%s/tags/*" % prefix
+
+ path = os.path.join(dirname, 'marks-git')
+
+ if os.path.exists(path):
+ print "*import-marks %s" % path
+ print "*export-marks %s" % path
+
print
def do_list(parser):
@@ -277,8 +328,108 @@ def do_import(parser):
tag = ref[len('refs/tags/'):]
export_tag(repo, tag)
+def parse_blob(parser):
+ global blob_marks
+
+ parser.next()
+ if parser.check('mark'):
+ mark = parser.get_mark()
+ parser.next()
+ data = parser.get_data()
+ blob_marks[mark] = data
+ return
+
+def parse_commit(parser):
+ global marks, blob_marks
+
+ from_mark = merge_mark = None
+
+ a = parser.line.split(' ')
+ ref = a[1]
+ if ref.startswith('refs/heads/'):
+ branch = ref[len('refs/heads/'):]
+ parser.next()
+
+ if parser.check('mark'):
+ commit_mark = parser.get_mark()
+ parser.next()
+ if parser.check('author'):
+ author = parser.get_author()
+ parser.next()
+ committer = parser.get_author()
+ parser.next()
+ data = parser.get_data()
+ parser.next()
+ if parser.check('from'):
+ from_mark = parser.get_mark()
+ parser.next()
+ if parser.check('merge'):
+ merge_mark = parser.get_mark()
+ parser.next()
+ if parser.check('merge'):
+ die('octopus merges are not supported yet')
+
+ files = {}
+
+ for line in parser:
+ if parser.check('M'):
+ t, mode, mark_ref, path = line.split(' ')
+ mark = int(mark_ref[1:])
+ f = { 'mode' : hgmode(mode), 'data' : blob_marks[mark] }
+ elif parser.check('D'):
+ t, path = line.split(' ')
+ f = { 'deleted' : True }
+ else:
+ die('Unknown file command: %s' % line)
+ files[path] = f
+
+ def getfilectx(repo, memctx, f):
+ of = files[f]
+ if 'deleted' in of:
+ raise IOError
+ return context.memfilectx(f, of['data'], False, False, None)
+
+ repo = parser.repo
+
+ committer_name, committer_email, date, tz = committer
+ date = int(date)
+ tz = int(tz)
+ tz = ((tz / 100) * 3600) + ((tz % 100) * 60)
+ extra = {}
+ extra['branch'] = branch
+
+ if from_mark:
+ p1 = repo.changelog.node(mark_to_rev(from_mark))
+ else:
+ p1 = '\0' * 20
+
+ if merge_mark:
+ p2 = repo.changelog.node(mark_to_rev(merge_mark))
+ else:
+ p2 = '\0' * 20
+
+ ctx = context.memctx(repo, (p1, p2), data,
+ files.keys(), getfilectx,
+ '%s <%s>' % (committer_name, committer_email), (date, -tz), extra)
+
+ node = repo.commitctx(ctx)
+ rev = repo[node].rev()
+
+ marks.new_mark(rev, commit_mark)
+
+ print "ok %s" % ref
+
+def do_export(parser):
+ for line in parser.each_block('done'):
+ if parser.check('blob'):
+ parse_blob(parser)
+ elif parser.check('commit'):
+ parse_commit(parser)
+ print
+
def main(args):
- global prefix, dirname, marks, branches
+ global prefix, dirname, branches
+ global marks, blob_marks
alias = args[1]
url = args[2]
@@ -286,6 +437,7 @@ def main(args):
gitdir = os.environ['GIT_DIR']
dirname = os.path.join(gitdir, 'hg', alias)
branches = {}
+ blob_marks = {}
repo = get_repo(url, alias)
prefix = 'refs/hg/%s' % alias
--
1.8.0.rc2.7.g0961fdf.dirty
^ permalink raw reply related
* [PATCH v3 1/6] Add new remote-hg transport helper
From: Felipe Contreras @ 2012-10-21 17:48 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Sverre Rabbelier, Johannes Schindelin,
Ilari Liusvaara, Daniel Barkalow, Jeff King, Michael J Gruber,
Felipe Contreras
In-Reply-To: <1350841744-21564-1-git-send-email-felipe.contreras@gmail.com>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
contrib/remote-hg/git-remote-hg | 313 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 313 insertions(+)
create mode 100755 contrib/remote-hg/git-remote-hg
diff --git a/contrib/remote-hg/git-remote-hg b/contrib/remote-hg/git-remote-hg
new file mode 100755
index 0000000..f0ce4a4
--- /dev/null
+++ b/contrib/remote-hg/git-remote-hg
@@ -0,0 +1,313 @@
+#!/usr/bin/python
+
+# Inspired by Rocco Rutte's hg-fast-export
+
+# Just copy to your ~/bin, or anywhere in your $PATH.
+# Then you can clone with:
+# git clone hg::/path/to/mercurial/repo/
+
+from mercurial import hg, ui
+
+import re
+import sys
+import os
+import json
+
+first = True
+
+AUTHOR_RE = re.compile('^((.+?) )?(<.+?>)$')
+
+def die(msg, *args):
+ sys.stderr.write('ERROR: %s\n' % (msg % args))
+ sys.exit(1)
+
+def warn(msg, *args):
+ sys.stderr.write('WARNING: %s\n' % (msg % args))
+
+def gitmode(flags):
+ return 'l' in flags and '120000' or 'x' in flags and '100755' or '100644'
+
+class Marks:
+
+ def __init__(self, path):
+ self.path = path
+ self.tips = {}
+ self.marks = {}
+ self.last_mark = 0
+
+ self.load()
+
+ def load(self):
+ if not os.path.exists(self.path):
+ return
+
+ tmp = json.load(open(self.path))
+
+ self.tips = tmp['tips']
+ self.marks = tmp['marks']
+ self.last_mark = tmp['last-mark']
+
+ def dict(self):
+ return { 'tips': self.tips, 'marks': self.marks, 'last-mark' : self.last_mark }
+
+ def store(self):
+ json.dump(self.dict(), open(self.path, 'w'))
+
+ def __str__(self):
+ return str(self.dict())
+
+ def from_rev(self, rev):
+ return self.marks[str(rev)]
+
+ def next_mark(self, rev):
+ self.last_mark += 1
+ self.marks[str(rev)] = self.last_mark
+ return self.last_mark
+
+ def is_marked(self, rev):
+ return self.marks.has_key(str(rev))
+
+ def get_tip(self, branch):
+ return self.tips.get(branch, 0)
+
+ def set_tip(self, branch, tip):
+ self.tips[branch] = tip
+
+class Parser:
+
+ def __init__(self, repo):
+ self.repo = repo
+ self.line = self.get_line()
+
+ def get_line(self):
+ return sys.stdin.readline().strip()
+
+ def __getitem__(self, i):
+ return self.line.split()[i]
+
+ def check(self, word):
+ return self.line.startswith(word)
+
+ def each_block(self, separator):
+ while self.line != separator:
+ yield self.line
+ self.line = self.get_line()
+
+ def __iter__(self):
+ return self.each_block('')
+
+def export_file(fc):
+ if fc.path() == '.hgtags':
+ return
+ d = fc.data()
+ print "M %s inline %s" % (gitmode(fc.flags()), fc.path())
+ print "data %d" % len(d)
+ print d
+
+def get_filechanges(repo, ctx, parents):
+ l = [repo.status(p, ctx)[:3] for p in parents]
+ changed, added, removed = [sum(e, []) for e in zip(*l)]
+ return added + changed, removed
+
+def fixup_user(user):
+ user = user.replace('"', '')
+ m = AUTHOR_RE.match(user)
+ if m:
+ name = m.group(2)
+ mail = m.group(3)
+ else:
+ name = user
+ mail = None
+
+ if not name:
+ name = 'Unknown'
+ if not mail:
+ mail = '<unknown>'
+
+ return '%s %s' % (name, mail)
+
+def get_repo(url, alias):
+ global dirname
+
+ myui = ui.ui()
+ myui.setconfig('ui', 'interactive', 'off')
+
+ if hg.islocal(url):
+ repo = hg.repository(myui, url)
+ else:
+ local_path = os.path.join(dirname, 'clone')
+ if not os.path.exists(local_path):
+ srcpeer, dstpeer = hg.clone(myui, {}, url, local_path, update=False, pull=True)
+ repo = dstpeer.local()
+ else:
+ repo = hg.repository(myui, local_path)
+ peer = hg.peer(myui, {}, url)
+ repo.pull(peer, heads=None, force=True)
+
+ return repo
+
+def rev_to_mark(rev):
+ global marks
+ return marks.from_rev(rev)
+
+def export_tag(repo, tag):
+ global prefix
+ print "reset %s/tags/%s" % (prefix, tag)
+ print "from :%s" % (rev_to_mark(repo[tag].rev()))
+ print
+
+def export_branch(repo, branch):
+ global prefix, marks, branches
+
+ heads = branches[branch]
+
+ # verify there's only one head
+ if (len(heads) > 1):
+ warn("Branch '%s' has more than one head, consider merging" % branch)
+ tip = repo.branchtip(branch)
+ head = repo[tip]
+ else:
+ head = repo[heads[0]]
+
+ tip = marks.get_tip(branch)
+ # mercurial takes too much time checking this
+ if tip and tip == head.rev():
+ # nothing to do
+ return
+ revs = repo.revs('%u:%u' % (tip, head))
+ count = 0
+
+ revs = [rev for rev in revs if not marks.is_marked(rev)]
+
+ for rev in revs:
+
+ c = repo[rev]
+ (manifest, user, (time, tz), files, desc, extra) = repo.changelog.read(c.node())
+ rev_branch = extra['branch']
+
+ tz = '%+03d%02d' % (-tz / 3600, -tz % 3600 / 60)
+
+ print "commit %s/branches/%s" % (prefix, rev_branch)
+ print "mark :%d" % (marks.next_mark(rev))
+ print "committer %s %d %s" % (fixup_user(user), time, tz)
+ print "data %d" % (len(desc) + 1)
+ print desc
+ print
+
+ parents = [p for p in repo.changelog.parentrevs(rev) if p >= 0]
+
+ if len(parents) == 0:
+ modified = c.manifest().keys()
+ removed = []
+ else:
+ added = []
+ changed = []
+ print "from :%s" % (rev_to_mark(parents[0]))
+ if len(parents) > 1:
+ print "merge :%s" % (rev_to_mark(parents[1]))
+ modified, removed = get_filechanges(repo, c, parents)
+
+ for f in removed:
+ print "D %s" % (f)
+ for f in modified:
+ export_file(c.filectx(f))
+ print
+
+ count += 1
+ if (count % 100 == 0):
+ print "progress revision %d '%s' (%d/%d)" % (rev, branch, count, len(revs))
+ print "#############################################################"
+
+ # make sure the ref is updated
+ print "reset %s/branches/%s" % (prefix, branch)
+ print "from :%u" % rev_to_mark(rev)
+ print
+
+ marks.set_tip(branch, rev)
+
+def do_capabilities(parser):
+ global prefix, dirname
+
+ print "import"
+ print "refspec refs/heads/*:%s/branches/*" % prefix
+ print "refspec refs/tags/*:%s/tags/*" % prefix
+ print
+
+def do_list(parser):
+ global branches
+
+ repo = parser.repo
+ head = repo.dirstate.branch()
+ for branch in repo.branchmap():
+ heads = repo.branchheads(branch)
+ if len(heads):
+ branches[branch] = heads
+
+ for branch in branches:
+ print "? refs/heads/%s" % branch
+ for tag, node in repo.tagslist():
+ if tag == 'tip':
+ continue
+ print "? refs/tags/%s" % tag
+ print "@refs/heads/%s HEAD" % head
+ print
+
+def do_import(parser):
+ global first
+
+ repo = parser.repo
+ ref = parser[1]
+
+ if first:
+ path = os.path.join(dirname, 'marks-git')
+
+ if os.path.exists(path):
+ print "feature import-marks=%s" % path
+ print "feature export-marks=%s" % path
+ sys.stdout.flush()
+ first = False
+
+ if (ref == 'HEAD'):
+ return
+
+ if ref.startswith('refs/heads/'):
+ branch = ref[len('refs/heads/'):]
+ export_branch(repo, branch)
+ elif ref.startswith('refs/tags/'):
+ tag = ref[len('refs/tags/'):]
+ export_tag(repo, tag)
+
+def main(args):
+ global prefix, dirname, marks, branches
+
+ alias = args[1]
+ url = args[2]
+
+ gitdir = os.environ['GIT_DIR']
+ dirname = os.path.join(gitdir, 'hg', alias)
+ branches = {}
+
+ repo = get_repo(url, alias)
+ prefix = 'refs/hg/%s' % alias
+
+ if not os.path.exists(dirname):
+ os.makedirs(dirname)
+
+ marks_path = os.path.join(dirname, 'marks-hg')
+ marks = Marks(marks_path)
+
+ parser = Parser(repo)
+ for line in parser:
+ if parser.check('capabilities'):
+ do_capabilities(parser)
+ elif parser.check('list'):
+ do_list(parser)
+ elif parser.check('import'):
+ do_import(parser)
+ elif parser.check('export'):
+ do_export(parser)
+ sys.stdout.flush()
+
+ marks.store()
+
+sys.exit(main(sys.argv))
--
1.8.0.rc2.7.g0961fdf.dirty
^ permalink raw reply related
* [PATCH v3 0/6] New remote-hg helper
From: Felipe Contreras @ 2012-10-21 17:48 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Sverre Rabbelier, Johannes Schindelin,
Ilari Liusvaara, Daniel Barkalow, Jeff King, Michael J Gruber,
Felipe Contreras
I've looked at many hg<->git tools and none satisfy me. Too complicated, or too
slow, or to difficult to setup, etc.
The only one I've liked so far is hg-fast-export[1], which is indeed fast,
relatively simple, and relatively easy to use. But it's not properly maintained
any more.
So, I decided to write my own from scratch, using hg-fast-export as
inspiration, and voila.
This one doesn't have any dependencies, just put it into your $PATH, and you
can clone and fetch hg repositories. More importantly to me; the code is
simple, and easy to maintain.
One important remote-hg alternative is the one written by Sverre Rabbelier that
is now maintained and distributed in msysgit, however, in my opinion the code
is bloated, and there isn't even a standalone branch to take a look at the
patches, and give them a try.
This version has some features that Sverre's version doesn't:
* Support for tags
* Support to specify branches to pull
Sverre's version has some features this one doesn't:
* Support for octopus merges
[1] http://repo.or.cz/w/fast-export.git
Changes since v2:
* Added support for pushing
* Tests copied from original remote-hg
* Custom default -> master renames removed
* Code reorganized
Changes since v1:
* Improved documentation
* Use more common 'python' binary
* Warn, don't barf when a branch has multiple heads
* Fixed marks to fetch after cloned
* Support for cloning/pulling remote repositories
* Use a more appropriate internal directory (e.g. .git/hg/origin)
* Fixes for python3
Felipe Contreras (6):
Add new remote-hg transport helper
remote-hg: add support for pushing
remote-hg: add support for remote pushing
remote-hg: add support for trivial features
tests: add remote-hg tests
tests: fix remote-hg warnings for modern git
contrib/remote-hg/git-remote-hg | 489 ++++++++++++++++++++++++++++++++++++++++
t/t5801-remote-hg.sh | 143 ++++++++++++
2 files changed, 632 insertions(+)
create mode 100755 contrib/remote-hg/git-remote-hg
create mode 100755 t/t5801-remote-hg.sh
--
1.8.0.rc2.7.g0961fdf.dirty
^ permalink raw reply
* Re: [PATCH 2/2] Fix failure to delete a packed ref through a symref
From: René Scharfe @ 2012-10-21 17:46 UTC (permalink / raw)
To: Johan Herland; +Cc: gitster, git, vmiklos
In-Reply-To: <1350816032-16312-3-git-send-email-johan@herland.net>
Am 21.10.2012 12:40, schrieb Johan Herland:
> When deleting a ref through a symref (e.g. using 'git update-ref -d HEAD'
> to delete refs/heads/master), we would remove the loose ref, but a packed
> version of the same ref would remain, the end result being that instead of
> deleting refs/heads/master we would appear to reset it to its state as of
> the last repack.
>
> This patch fixes the issue, by making sure we pass the correct ref name
> when invoking repack_without_ref() from within delete_ref().
>
> Signed-off-by: Johan Herland <johan@herland.net>
> ---
> refs.c | 2 +-
> t/t1400-update-ref.sh | 2 +-
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/refs.c b/refs.c
> index 726c53c..6cec1c8 100644
> --- a/refs.c
> +++ b/refs.c
> @@ -1779,7 +1779,7 @@ int delete_ref(const char *refname, const unsigned char *sha1, int delopt)
> * packed one. Also, if it was not loose we need to repack
> * without it.
> */
> - ret |= repack_without_ref(refname);
> + ret |= repack_without_ref(lock->ref_name);
>
> unlink_or_warn(git_path("logs/%s", lock->ref_name));
> invalidate_ref_cache(NULL);
Looks reasonable.
FWIW, this is independent of 547d058f in next (refs: lock symref that is
to be deleted, not its target), which only affects behaviour when
REF_NODEREF is set, while this one here only makes a difference with
symrefs and REF_NODEREF unset.
René
^ permalink raw reply
* Re: Subtree in Git
From: Herman van Rink @ 2012-10-21 15:09 UTC (permalink / raw)
To: Junio C Hamano; +Cc: dag, greened, Hilco Wijbenga, Git Users
In-Reply-To: <7vbofwgwso.fsf@alter.siamese.dyndns.org>
On 10/21/2012 08:32 AM, Junio C Hamano wrote:
> Herman van Rink <rink@initfour.nl> writes:
>
>> Junio, Could you please consider merging the single commit from my
>> subtree-updates branch? https://github.com/helmo/git/tree/subtree-updates
> In general, in areas like contrib/ where there is a volunteer area
> maintainer, unless the change something ultra-urgent (e.g. serious
> security fix) and the area maintainer is unavailable, I'm really
> reluctant to bypass and take a single patch that adds many things
> that are independent from each other.
Who do you see as volunteer area maintainer for contrib/subtree?
My best guess would be Dave. And he already indicated earlier in the
thread to be ok with the combined patch as long as you are ok with it.
>
> Especially not immediately before tagging 1.8.0 final.
Sure, we've waited this long... I don't mind waiting one more release cycle.
--
Met vriendelijke groet / Regards,
Herman van Rink
Initfour websolutions
^ permalink raw reply
* Re: In search of a version control system
From: Sitaram Chamarty @ 2012-10-21 13:25 UTC (permalink / raw)
To: Drew Northup
Cc: Matthieu Moy, David Aguilar, Ramkumar Ramachandra,
Maurice Francois, git@vger.kernel.org
In-Reply-To: <CAM9Z-nnQjhehJEpyhyTY=rsK_f=2gTOUMVTycn7-Lao8Gog0pA@mail.gmail.com>
On Sun, Oct 21, 2012 at 5:50 PM, Drew Northup <n1xim.email@gmail.com> wrote:
> On Tue, Oct 9, 2012 at 1:58 AM, Matthieu Moy
> <Matthieu.Moy@grenoble-inp.fr> wrote:
>> David Aguilar <davvid@gmail.com> writes:
>>
>>> I would advise against the file locking, though. You ain't gonna need
>>> it ;-)
>>
>> What do you suggest to merge Word files?
>
> If the files are in the DOCX format you can just expand them as zip
> archives and diff what's inside of them. The text in particular is
> stored as XML.
You also need a merge driver that at least splits the "all in one
single very very long line" XML into different lines in some way. I
don't think git can merge even text files if everything is on one line
in each file. And even if you do this I don't think the result will
be a valid ODT etc file.
All in all, I prefer the locking that David mentioned [1]. And if
your users cannot be trained to check first (as that URL describes),
then you probably have to use a CVCS that supports some stronger form
of locking.
[1]: http://sitaramc.github.com/gitolite/locking.html
^ permalink raw reply
* Re: In search of a version control system
From: Nguyen Thai Ngoc Duy @ 2012-10-21 13:16 UTC (permalink / raw)
To: Drew Northup
Cc: Matthieu Moy, David Aguilar, Ramkumar Ramachandra,
Maurice Francois, git@vger.kernel.org
In-Reply-To: <CAM9Z-nnQjhehJEpyhyTY=rsK_f=2gTOUMVTycn7-Lao8Gog0pA@mail.gmail.com>
On Sun, Oct 21, 2012 at 7:20 PM, Drew Northup <n1xim.email@gmail.com> wrote:
> On Tue, Oct 9, 2012 at 1:58 AM, Matthieu Moy
> <Matthieu.Moy@grenoble-inp.fr> wrote:
>> David Aguilar <davvid@gmail.com> writes:
>>
>>> I would advise against the file locking, though. You ain't gonna need
>>> it ;-)
>>
>> What do you suggest to merge Word files?
>
> If the files are in the DOCX format you can just expand them as zip
> archives and diff what's inside of them. The text in particular is
> stored as XML.
An XML diff means nothing to a regular user, and manually "merging"
this way can produce unreadable Words files. So no, it's still not an
answer.
--
Duy
^ permalink raw reply
* Re: In search of a version control system
From: Drew Northup @ 2012-10-21 12:20 UTC (permalink / raw)
To: Matthieu Moy
Cc: David Aguilar, Ramkumar Ramachandra, Maurice Francois,
git@vger.kernel.org
In-Reply-To: <vpq4nm4rxsy.fsf@grenoble-inp.fr>
On Tue, Oct 9, 2012 at 1:58 AM, Matthieu Moy
<Matthieu.Moy@grenoble-inp.fr> wrote:
> David Aguilar <davvid@gmail.com> writes:
>
>> I would advise against the file locking, though. You ain't gonna need
>> it ;-)
>
> What do you suggest to merge Word files?
If the files are in the DOCX format you can just expand them as zip
archives and diff what's inside of them. The text in particular is
stored as XML.
--
-Drew Northup
--------------------------------------------------------------
"As opposed to vegetable or mineral error?"
-John Pescatore, SANS NewsBites Vol. 12 Num. 59
^ permalink raw reply
* Re: git fetch documentation problem or bug
From: Drew Northup @ 2012-10-21 12:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Angelo Borsotti, Carlos Martín Nieto, Matthieu Moy,
Nguyễn Thái Ngọc
In-Reply-To: <7vpq4silou.fsf@alter.siamese.dyndns.org>
On Mon, Oct 8, 2012 at 7:33 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Junio C Hamano <gitster@pobox.com> writes:
>
>> In other words, you can do this from the command line if you want
>> to do the update.
>>
>> $ git fetch origin master:refs/remotes/origin/master
>
> Now having said all that, we should probably revisit this and
> possibly other issues and for the ones we can reach concensus, start
> coding after 1.8.0 final.
> * "git fetch $from $branch..." to update tracking branches
>
> This is the topic in this thread.
>
> I personally do not think the downside of breaking backward
> compatibility is too bad. If we do this only when we already are
> configured to keep remote tracking branch for branch $branch from
> remote $from (it has to be given as a nickname, not URL that happens
> to have an entry in the configuration), then a promiscuous fetch
> that grabs from a URL (or a nickname that is configured not to keep
> tracking branches) will not change any behaviour, and when you want
> to keep your remote tracking branch intact while doing one-shot
> fetch for whatever reason, you can say "git fetch $from $branch:" to
> explicitly decline copying.
How are we supposed to remember those are different?
"git fetch $from $branch..."
VS
"git fetch $from $branch:"
I strongly prefer EXPLICITLY setting tracking than expecting some
extreme syntactic nuance to quietly do it for me now and confuse the
heck out of me later.
--
-Drew Northup
--------------------------------------------------------------
"As opposed to vegetable or mineral error?"
-John Pescatore, SANS NewsBites Vol. 12 Num. 59
^ permalink raw reply
* Re: looking for suggestions for managing a tree of server configs
From: Drew Northup @ 2012-10-21 11:58 UTC (permalink / raw)
To: david; +Cc: Junio C Hamano, git
In-Reply-To: <alpine.DEB.2.02.1210201931130.31862@asgard.lang.hm>
On Sat, Oct 20, 2012 at 10:34 PM, <david@lang.hm> wrote:
> On Sat, 20 Oct 2012, Drew Northup wrote:
>> On Sun, Oct 14, 2012 at 12:57 AM, <david@lang.hm> wrote:
>>> On Sat, 13 Oct 2012, Junio C Hamano wrote:
>>>> david@lang.hm writes:
>>>>>
>>>>> today I have just a single git tree covering everything, and I make a
>>>>> commit each time one of the per-server directories is updated, and
>>>>> again when the top-level stuff is created.
>>>>
>>>> if a large portion of the configuration for these servers are
>>>> shared, it might not be a bad idea to have a canonical "gold-master"
>>>> configuration branch, to which the shared updates are applied, with
>>>> a branch per server that forks from that canonical branch to keep
>>>> the machine specific tweaks
>>>
>>> In an ideal world yes, but right now these machines are updated by many
>>> different tools (unforuntantly including 'vi'), so
>>> these directories aren't the config to be pushed out to the boxes, it's
>>> instead an archived 'what is', the result of changes from all the tools.
So you need to save what is there before pulling changes from the
master. That's no different from doing development work on an active
code base.
>> David,
>> Is there any particular reason you aren't using etckeeper?
>>
> not really, I've thought of that as a tool for managing a single system.
> Some of the data in configs is sensitive (and much of it is not in /etc),
> but I guess I should be able to work around those issues.
.gitignore and symlinks have been employed at times to deal with that.
> How can I sanely organize all these different, but similar sets of files on
> the central server?
The reason I asked about etckeeper is that you could, with proper
security in place, push those up to branches in a shared repository
(set up using gitolite, for instance) and not loose information about
the files in the process. This would allow you to make your changes on
one system using vi or whatever else is convenient, push the change up
to the shared repo, cherry-pick it into the other branches (using a
full check-out of all of the branches someplace safe as a workspace),
and pull that change out to the other systems.
If you are just looking to gather configuration information in the
large and don't want to engage in any shared management schemes (which
may involve symlinks in seemingly odd places to /etc and such) you may
wish to look at the System Configuration Collector [1] [2] which is a
nicely organized tool designed specifically to gather just the
important (and not highly confidential) information about common
software on a server and present it (and changes to it) to the admin
in a sensible manner. It is outside of the "Git Universe" but it does
what it sounds like you are doing now (if not what you wish to be
doing).
(1) http://www.qnh.eu/scc/
(2) http://sourceforge.net/projects/sysconfcollect/
--
-Drew Northup
--------------------------------------------------------------
"As opposed to vegetable or mineral error?"
-John Pescatore, SANS NewsBites Vol. 12 Num. 59
^ permalink raw reply
* [RFC/PATCH] git symbolic-ref --delete $symref
From: Johan Herland @ 2012-10-21 11:32 UTC (permalink / raw)
To: gitster; +Cc: git, Johan Herland
Teach symbolic-ref to delete symrefs by adding the -d/--delete option to
git-symbolic-ref. Both proper and dangling symrefs are deleted by this
option, but other refs - or anything else that is not a symref - is not.
The symref deletion is performed by first verifying that we are given a
proper symref, and then invoking delete_ref() on it with the REF_NODEREF
flag.
Signed-off-by: Johan Herland <johan@herland.net>
---
Here is a quick first attempt at implementing the 'git symbolic-ref -d'
you've been mentioning in the symref deletion thread.
Documentation/git-symbolic-ref.txt | 10 +++++++++-
builtin/symbolic-ref.c | 33 +++++++++++++++++++++++----------
t/t1401-symbolic-ref.sh | 30 ++++++++++++++++++++++++++++++
3 files changed, 62 insertions(+), 11 deletions(-)
diff --git a/Documentation/git-symbolic-ref.txt b/Documentation/git-symbolic-ref.txt
index 981d3a8..ef68ad2 100644
--- a/Documentation/git-symbolic-ref.txt
+++ b/Documentation/git-symbolic-ref.txt
@@ -3,13 +3,14 @@ git-symbolic-ref(1)
NAME
----
-git-symbolic-ref - Read and modify symbolic refs
+git-symbolic-ref - Read, modify and delete symbolic refs
SYNOPSIS
--------
[verse]
'git symbolic-ref' [-m <reason>] <name> <ref>
'git symbolic-ref' [-q] [--short] <name>
+'git symbolic-ref' --delete [-q] <name>
DESCRIPTION
-----------
@@ -21,6 +22,9 @@ argument to see which branch your working tree is on.
Given two arguments, creates or updates a symbolic ref <name> to
point at the given branch <ref>.
+Given `--delete` and an additional argument, deletes the given
+symbolic ref.
+
A symbolic ref is a regular file that stores a string that
begins with `ref: refs/`. For example, your `.git/HEAD` is
a regular file whose contents is `ref: refs/heads/master`.
@@ -28,6 +32,10 @@ a regular file whose contents is `ref: refs/heads/master`.
OPTIONS
-------
+-d::
+--delete::
+ Delete the symbolic ref <name>.
+
-q::
--quiet::
Do not issue an error message if the <name> is not a
diff --git a/builtin/symbolic-ref.c b/builtin/symbolic-ref.c
index 9e92828..f481959 100644
--- a/builtin/symbolic-ref.c
+++ b/builtin/symbolic-ref.c
@@ -5,12 +5,11 @@
static const char * const git_symbolic_ref_usage[] = {
N_("git symbolic-ref [options] name [ref]"),
+ N_("git symbolic-ref -d [-q] name"),
NULL
};
-static int shorten;
-
-static void check_symref(const char *HEAD, int quiet)
+static int check_symref(const char *HEAD, int quiet, int shorten, int print)
{
unsigned char sha1[20];
int flag;
@@ -22,20 +21,24 @@ static void check_symref(const char *HEAD, int quiet)
if (!quiet)
die("ref %s is not a symbolic ref", HEAD);
else
- exit(1);
+ return 1;
+ }
+ if (print) {
+ if (shorten)
+ refname = shorten_unambiguous_ref(refname, 0);
+ puts(refname);
}
- if (shorten)
- refname = shorten_unambiguous_ref(refname, 0);
- puts(refname);
+ return 0;
}
int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
{
- int quiet = 0;
+ int quiet = 0, delete = 0, shorten = 0, ret = 0;
const char *msg = NULL;
struct option options[] = {
OPT__QUIET(&quiet,
N_("suppress error message for non-symbolic (detached) refs")),
+ OPT_BOOL('d', "delete", &delete, N_("delete symbolic ref")),
OPT_BOOL(0, "short", &shorten, N_("shorten ref output")),
OPT_STRING('m', NULL, &msg, N_("reason"), N_("reason of the update")),
OPT_END(),
@@ -46,9 +49,19 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
git_symbolic_ref_usage, 0);
if (msg &&!*msg)
die("Refusing to perform update with empty message");
+
+ if (delete) {
+ if (argc != 1)
+ usage_with_options(git_symbolic_ref_usage, options);
+ ret = check_symref(argv[0], 1, 0, 0);
+ if (ret)
+ die("Cannot delete %s, not a symbolic ref", argv[0]);
+ return delete_ref(argv[0], NULL, REF_NODEREF);
+ }
+
switch (argc) {
case 1:
- check_symref(argv[0], quiet);
+ ret = check_symref(argv[0], quiet, shorten, 1);
break;
case 2:
if (!strcmp(argv[0], "HEAD") &&
@@ -59,5 +72,5 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
default:
usage_with_options(git_symbolic_ref_usage, options);
}
- return 0;
+ return ret;
}
diff --git a/t/t1401-symbolic-ref.sh b/t/t1401-symbolic-ref.sh
index 2c96551..36378b0 100755
--- a/t/t1401-symbolic-ref.sh
+++ b/t/t1401-symbolic-ref.sh
@@ -33,4 +33,34 @@ test_expect_success 'symbolic-ref refuses bare sha1' '
'
reset_to_sane
+test_expect_success 'symbolic-ref deletes HEAD' '
+ git symbolic-ref -d HEAD &&
+ test_path_is_file .git/refs/heads/foo &&
+ test_path_is_missing .git/HEAD
+'
+reset_to_sane
+
+test_expect_success 'symbolic-ref deletes dangling HEAD' '
+ git symbolic-ref HEAD refs/heads/missing &&
+ git symbolic-ref -d HEAD &&
+ test_path_is_missing .git/refs/heads/missing &&
+ test_path_is_missing .git/HEAD
+'
+reset_to_sane
+
+test_expect_success 'symbolic-ref fails to delete missing FOO' '
+ echo "fatal: Cannot delete FOO, not a symbolic ref" >expect &&
+ test_must_fail git symbolic-ref -d FOO >actual 2>&1 &&
+ test_cmp expect actual
+'
+reset_to_sane
+
+test_expect_success 'symbolic-ref fails to delete real ref' '
+ echo "fatal: Cannot delete refs/heads/foo, not a symbolic ref" >expect &&
+ test_must_fail git symbolic-ref -d refs/heads/foo >actual 2>&1 &&
+ test_path_is_file .git/refs/heads/foo &&
+ test_cmp expect actual
+'
+reset_to_sane
+
test_done
--
1.7.12.1.609.g5cd6968
^ permalink raw reply related
* [PATCH 1/2] t1400-update-ref: Add test verifying bug with symrefs in delete_ref()
From: Johan Herland @ 2012-10-21 10:40 UTC (permalink / raw)
To: gitster; +Cc: git, rene.scharfe, vmiklos, Johan Herland
In-Reply-To: <1350816032-16312-1-git-send-email-johan@herland.net>
When deleting a ref through a symref (e.g. using 'git update-ref -d HEAD'
to delete refs/heads/master), we currently fail to remove the packed
version of that ref. This testcase demonstrates the bug.
Signed-off-by: Johan Herland <johan@herland.net>
---
t/t1400-update-ref.sh | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index 4fd83a6..f7ec203 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -74,6 +74,24 @@ test_expect_success "delete $m (by HEAD)" '
'
rm -f .git/$m
+test_expect_success \
+ "create $m (by HEAD)" \
+ "git update-ref HEAD $A &&
+ test $A"' = $(cat .git/'"$m"')'
+test_expect_success \
+ "pack refs" \
+ "git pack-refs --all"
+test_expect_success \
+ "move $m (by HEAD)" \
+ "git update-ref HEAD $B $A &&
+ test $B"' = $(cat .git/'"$m"')'
+test_expect_failure "delete $m (by HEAD) should remove both packed and loose $m" '
+ git update-ref -d HEAD $B &&
+ ! grep "$m" .git/packed-refs &&
+ ! test -f .git/$m
+'
+rm -f .git/$m
+
cp -f .git/HEAD .git/HEAD.orig
test_expect_success "delete symref without dereference" '
git update-ref --no-deref -d HEAD &&
--
1.7.12.1.609.g5cd6968
^ permalink raw reply related
* [PATCH 2/2] Fix failure to delete a packed ref through a symref
From: Johan Herland @ 2012-10-21 10:40 UTC (permalink / raw)
To: gitster; +Cc: git, rene.scharfe, vmiklos, Johan Herland
In-Reply-To: <1350816032-16312-1-git-send-email-johan@herland.net>
When deleting a ref through a symref (e.g. using 'git update-ref -d HEAD'
to delete refs/heads/master), we would remove the loose ref, but a packed
version of the same ref would remain, the end result being that instead of
deleting refs/heads/master we would appear to reset it to its state as of
the last repack.
This patch fixes the issue, by making sure we pass the correct ref name
when invoking repack_without_ref() from within delete_ref().
Signed-off-by: Johan Herland <johan@herland.net>
---
refs.c | 2 +-
t/t1400-update-ref.sh | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/refs.c b/refs.c
index 726c53c..6cec1c8 100644
--- a/refs.c
+++ b/refs.c
@@ -1779,7 +1779,7 @@ int delete_ref(const char *refname, const unsigned char *sha1, int delopt)
* packed one. Also, if it was not loose we need to repack
* without it.
*/
- ret |= repack_without_ref(refname);
+ ret |= repack_without_ref(lock->ref_name);
unlink_or_warn(git_path("logs/%s", lock->ref_name));
invalidate_ref_cache(NULL);
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index f7ec203..e415ee0 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -85,7 +85,7 @@ test_expect_success \
"move $m (by HEAD)" \
"git update-ref HEAD $B $A &&
test $B"' = $(cat .git/'"$m"')'
-test_expect_failure "delete $m (by HEAD) should remove both packed and loose $m" '
+test_expect_success "delete $m (by HEAD) should remove both packed and loose $m" '
git update-ref -d HEAD $B &&
! grep "$m" .git/packed-refs &&
! test -f .git/$m
--
1.7.12.1.609.g5cd6968
^ 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