* [PATCH v2 4/4] branch: show more information when HEAD is detached
From: Nguyễn Thái Ngọc Duy @ 2013-03-06 12:21 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Matthieu Moy, Jonathan Niedier,
Nguyễn Thái Ngọc Duy
In-Reply-To: <1362572482-20570-1-git-send-email-pclouds@gmail.com>
This prints more helpful info when HEAD is detached: is it detached
because of bisect or rebase? What is the original branch name in those
cases? Is it detached because the user checks out a remote ref or a
tag (and which one)?
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
builtin/branch.c | 25 ++++++++++++++++++++++++-
t/t3203-branch-output.sh | 6 +++---
t/t6030-bisect-porcelain.sh | 2 +-
3 files changed, 28 insertions(+), 5 deletions(-)
diff --git a/builtin/branch.c b/builtin/branch.c
index 6371bf9..02dee0d 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -18,6 +18,7 @@
#include "string-list.h"
#include "column.h"
#include "utf8.h"
+#include "wt-status.h"
static const char * const builtin_branch_usage[] = {
N_("git branch [options] [-r | -a] [--merged | --no-merged]"),
@@ -550,6 +551,28 @@ static int calc_maxwidth(struct ref_list *refs)
return w;
}
+static char *get_head_description()
+{
+ struct strbuf desc = STRBUF_INIT;
+ struct wt_status_state state;
+ wt_status_get_state(&state, 1);
+ if (state.rebase_in_progress ||
+ state.rebase_interactive_in_progress)
+ strbuf_addf(&desc, _("(no branch, rebasing %s)"),
+ state.branch);
+ else if (state.bisect_in_progress)
+ strbuf_addf(&desc, _("(no branch, bisecting %s)"),
+ state.branch);
+ else if (state.detached_from)
+ strbuf_addf(&desc, _("(detached from %s)"),
+ state.detached_from);
+ else
+ strbuf_addstr(&desc, _("(no branch)"));
+ free(state.branch);
+ free(state.onto);
+ free(state.detached_from);
+ return strbuf_detach(&desc, NULL);
+}
static void show_detached(struct ref_list *ref_list)
{
@@ -557,7 +580,7 @@ static void show_detached(struct ref_list *ref_list)
if (head_commit && is_descendant_of(head_commit, ref_list->with_commit)) {
struct ref_item item;
- item.name = xstrdup(_("(no branch)"));
+ item.name = get_head_description();
item.width = utf8_strwidth(item.name);
item.kind = REF_LOCAL_BRANCH;
item.dest = NULL;
diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh
index 76fe7e0..ba4f98e 100755
--- a/t/t3203-branch-output.sh
+++ b/t/t3203-branch-output.sh
@@ -94,13 +94,13 @@ test_expect_success 'git branch -v pattern does not show branch summaries' '
test_must_fail git branch -v branch*
'
-cat >expect <<'EOF'
-* (no branch)
+test_expect_success 'git branch shows detached HEAD properly' '
+ cat >expect <<EOF &&
+* (detached from $(git rev-parse --short HEAD^0))
branch-one
branch-two
master
EOF
-test_expect_success 'git branch shows detached HEAD properly' '
git checkout HEAD^0 &&
git branch >actual &&
test_i18ncmp expect actual
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index 3e0e15f..9b6f0d0 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -164,7 +164,7 @@ test_expect_success 'bisect start: existing ".git/BISECT_START" not modified if
cp .git/BISECT_START saved &&
test_must_fail git bisect start $HASH4 foo -- &&
git branch > branch.output &&
- test_i18ngrep "* (no branch)" branch.output > /dev/null &&
+ test_i18ngrep "* (no branch, bisecting other)" branch.output > /dev/null &&
test_cmp saved .git/BISECT_START
'
test_expect_success 'bisect start: no ".git/BISECT_START" if mistaken rev' '
--
1.8.1.2.536.gf441e6d
^ permalink raw reply related
* [PATCH v2 3/4] status: show more info than "currently not on any branch"
From: Nguyễn Thái Ngọc Duy @ 2013-03-06 12:21 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Matthieu Moy, Jonathan Niedier,
Nguyễn Thái Ngọc Duy
In-Reply-To: <1362572482-20570-1-git-send-email-pclouds@gmail.com>
When a remote ref or a tag is checked out, HEAD is automatically
detached. There is no user-friendly way to find out what ref is
checked out in this case. This patch digs in reflog for this
information and shows "HEAD detached from origin/master" or "HEAD
detached at v1.8.0" instead of "currently not on any branch".
When it cannot figure out the original ref, it shows an abbreviated
SHA-1. "Currently not on any branch" would never display (unless
reflog is pruned to near empty that the last checkout entry is lost).
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
t/t7406-submodule-update.sh | 6 ++--
t/t7512-status-help.sh | 52 +++++++++++++++++----------
wt-status.c | 85 ++++++++++++++++++++++++++++++++++++++++++---
wt-status.h | 4 ++-
4 files changed, 121 insertions(+), 26 deletions(-)
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index 4975ec0..50ac020 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -664,8 +664,10 @@ test_expect_success 'submodule add properly re-creates deeper level submodules'
test_expect_success 'submodule update properly revives a moved submodule' '
(cd super &&
+ H=$(git rev-parse --short HEAD) &&
git commit -am "pre move" &&
- git status >expect&&
+ H2=$(git rev-parse --short HEAD) &&
+ git status | sed "s/$H/XXX/" >expect &&
H=$(cd submodule2; git rev-parse HEAD) &&
git rm --cached submodule2 &&
rm -rf submodule2 &&
@@ -674,7 +676,7 @@ test_expect_success 'submodule update properly revives a moved submodule' '
git config -f .gitmodules submodule.submodule2.path "moved/sub module"
git commit -am "post move" &&
git submodule update &&
- git status >actual &&
+ git status | sed "s/$H2/XXX/" >actual &&
test_cmp expect actual
)
'
diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
index d2da89a..da22088 100755
--- a/t/t7512-status-help.sh
+++ b/t/t7512-status-help.sh
@@ -76,7 +76,7 @@ test_expect_success 'status when rebase in progress before resolving conflicts'
ONTO=$(git rev-parse --short HEAD^^) &&
test_must_fail git rebase HEAD^ --onto HEAD^^ &&
cat >expected <<-EOF &&
- # Not currently on any branch.
+ # HEAD detached at $ONTO
# You are currently rebasing branch '\''rebase_conflicts'\'' on '\''$ONTO'\''.
# (fix conflicts and then run "git rebase --continue")
# (use "git rebase --skip" to skip this patch)
@@ -103,7 +103,7 @@ test_expect_success 'status when rebase in progress before rebase --continue' '
echo three >main.txt &&
git add main.txt &&
cat >expected <<-EOF &&
- # Not currently on any branch.
+ # HEAD detached at $ONTO
# You are currently rebasing branch '\''rebase_conflicts'\'' on '\''$ONTO'\''.
# (all conflicts fixed: run "git rebase --continue")
#
@@ -135,7 +135,7 @@ test_expect_success 'status during rebase -i when conflicts unresolved' '
ONTO=$(git rev-parse --short rebase_i_conflicts) &&
test_must_fail git rebase -i rebase_i_conflicts &&
cat >expected <<-EOF &&
- # Not currently on any branch.
+ # HEAD detached at $ONTO
# You are currently rebasing branch '\''rebase_i_conflicts_second'\'' on '\''$ONTO'\''.
# (fix conflicts and then run "git rebase --continue")
# (use "git rebase --skip" to skip this patch)
@@ -161,7 +161,7 @@ test_expect_success 'status during rebase -i after resolving conflicts' '
test_must_fail git rebase -i rebase_i_conflicts &&
git add main.txt &&
cat >expected <<-EOF &&
- # Not currently on any branch.
+ # HEAD detached at $ONTO
# You are currently rebasing branch '\''rebase_i_conflicts_second'\'' on '\''$ONTO'\''.
# (all conflicts fixed: run "git rebase --continue")
#
@@ -187,9 +187,10 @@ test_expect_success 'status when rebasing -i in edit mode' '
export FAKE_LINES &&
test_when_finished "git rebase --abort" &&
ONTO=$(git rev-parse --short HEAD~2) &&
+ TGT=$(git rev-parse --short two_rebase_i) &&
git rebase -i HEAD~2 &&
cat >expected <<-EOF &&
- # Not currently on any branch.
+ # HEAD detached from $TGT
# You are currently editing a commit while rebasing branch '\''rebase_i_edit'\'' on '\''$ONTO'\''.
# (use "git commit --amend" to amend the current commit)
# (use "git rebase --continue" once you are satisfied with your changes)
@@ -214,8 +215,9 @@ test_expect_success 'status when splitting a commit' '
ONTO=$(git rev-parse --short HEAD~3) &&
git rebase -i HEAD~3 &&
git reset HEAD^ &&
+ TGT=$(git rev-parse --short HEAD) &&
cat >expected <<-EOF &&
- # Not currently on any branch.
+ # HEAD detached at $TGT
# You are currently splitting a commit while rebasing branch '\''split_commit'\'' on '\''$ONTO'\''.
# (Once your working directory is clean, run "git rebase --continue")
#
@@ -243,10 +245,11 @@ test_expect_success 'status after editing the last commit with --amend during a
export FAKE_LINES &&
test_when_finished "git rebase --abort" &&
ONTO=$(git rev-parse --short HEAD~3) &&
+ TGT=$(git rev-parse --short three_amend) &&
git rebase -i HEAD~3 &&
git commit --amend -m "foo" &&
cat >expected <<-EOF &&
- # Not currently on any branch.
+ # HEAD detached from $TGT
# You are currently editing a commit while rebasing branch '\''amend_last'\'' on '\''$ONTO'\''.
# (use "git commit --amend" to amend the current commit)
# (use "git rebase --continue" once you are satisfied with your changes)
@@ -276,7 +279,7 @@ test_expect_success 'status: (continue first edit) second edit' '
git rebase -i HEAD~3 &&
git rebase --continue &&
cat >expected <<-EOF &&
- # Not currently on any branch.
+ # HEAD detached from $ONTO
# You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
# (use "git commit --amend" to amend the current commit)
# (use "git rebase --continue" once you are satisfied with your changes)
@@ -298,7 +301,7 @@ test_expect_success 'status: (continue first edit) second edit and split' '
git rebase --continue &&
git reset HEAD^ &&
cat >expected <<-EOF &&
- # Not currently on any branch.
+ # HEAD detached from $ONTO
# You are currently splitting a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
# (Once your working directory is clean, run "git rebase --continue")
#
@@ -325,7 +328,7 @@ test_expect_success 'status: (continue first edit) second edit and amend' '
git rebase --continue &&
git commit --amend -m "foo" &&
cat >expected <<-EOF &&
- # Not currently on any branch.
+ # HEAD detached from $ONTO
# You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
# (use "git commit --amend" to amend the current commit)
# (use "git rebase --continue" once you are satisfied with your changes)
@@ -347,7 +350,7 @@ test_expect_success 'status: (amend first edit) second edit' '
git commit --amend -m "a" &&
git rebase --continue &&
cat >expected <<-EOF &&
- # Not currently on any branch.
+ # HEAD detached from $ONTO
# You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
# (use "git commit --amend" to amend the current commit)
# (use "git rebase --continue" once you are satisfied with your changes)
@@ -370,7 +373,7 @@ test_expect_success 'status: (amend first edit) second edit and split' '
git rebase --continue &&
git reset HEAD^ &&
cat >expected <<-EOF &&
- # Not currently on any branch.
+ # HEAD detached from $ONTO
# You are currently splitting a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
# (Once your working directory is clean, run "git rebase --continue")
#
@@ -398,7 +401,7 @@ test_expect_success 'status: (amend first edit) second edit and amend' '
git rebase --continue &&
git commit --amend -m "d" &&
cat >expected <<-EOF &&
- # Not currently on any branch.
+ # HEAD detached from $ONTO
# You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
# (use "git commit --amend" to amend the current commit)
# (use "git rebase --continue" once you are satisfied with your changes)
@@ -422,7 +425,7 @@ test_expect_success 'status: (split first edit) second edit' '
git commit -m "e" &&
git rebase --continue &&
cat >expected <<-EOF &&
- # Not currently on any branch.
+ # HEAD detached from $ONTO
# You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
# (use "git commit --amend" to amend the current commit)
# (use "git rebase --continue" once you are satisfied with your changes)
@@ -447,7 +450,7 @@ test_expect_success 'status: (split first edit) second edit and split' '
git rebase --continue &&
git reset HEAD^ &&
cat >expected <<-EOF &&
- # Not currently on any branch.
+ # HEAD detached from $ONTO
# You are currently splitting a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
# (Once your working directory is clean, run "git rebase --continue")
#
@@ -477,7 +480,7 @@ test_expect_success 'status: (split first edit) second edit and amend' '
git rebase --continue &&
git commit --amend -m "h" &&
cat >expected <<-EOF &&
- # Not currently on any branch.
+ # HEAD detached from $ONTO
# You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
# (use "git commit --amend" to amend the current commit)
# (use "git rebase --continue" once you are satisfied with your changes)
@@ -572,8 +575,9 @@ test_expect_success 'status when bisecting' '
git bisect start &&
git bisect bad &&
git bisect good one_bisect &&
- cat >expected <<-\EOF &&
- # Not currently on any branch.
+ TGT=$(git rev-parse --short two_bisect) &&
+ cat >expected <<-EOF &&
+ # HEAD detached at $TGT
# You are currently bisecting branch '\''bisect'\''.
# (use "git bisect reset" to get back to the original branch)
#
@@ -596,7 +600,7 @@ test_expect_success 'status when rebase conflicts with statushints disabled' '
ONTO=$(git rev-parse --short HEAD^^) &&
test_must_fail git rebase HEAD^ --onto HEAD^^ &&
cat >expected <<-EOF &&
- # Not currently on any branch.
+ # HEAD detached at $ONTO
# You are currently rebasing branch '\''statushints_disabled'\'' on '\''$ONTO'\''.
#
# Unmerged paths:
@@ -662,5 +666,15 @@ test_expect_success 'status when cherry-picking after resolving conflicts' '
test_i18ncmp expected actual
'
+test_expect_success 'status showing detached from a tag' '
+ test_commit atag tagging &&
+ git checkout atag &&
+ cat >expected <<-\EOF
+ # HEAD detached at atag
+ nothing to commit (use -u to show untracked files)
+ EOF
+ git status --untracked-files=no >actual &&
+ test_i18ncmp expected actual
+'
test_done
diff --git a/wt-status.c b/wt-status.c
index 6a3566b..7797ccf 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -1001,7 +1001,68 @@ static void read_and_strip_branch(struct strbuf *sb,
*branch = xstrdup(*branch);
}
-void wt_status_get_state(struct wt_status_state *state)
+struct grab_1st_switch_cbdata {
+ struct strbuf buf;
+ unsigned char nsha1[20];
+};
+
+static int grab_1st_switch(unsigned char *osha1, unsigned char *nsha1,
+ const char *email, unsigned long timestamp, int tz,
+ const char *message, void *cb_data)
+{
+ struct grab_1st_switch_cbdata *cb = cb_data;
+ const char *target = NULL, *end;
+
+ if (prefixcmp(message, "checkout: moving from "))
+ return 0;
+ message += strlen("checkout: moving from ");
+ target = strstr(message, " to ");
+ if (!target)
+ return 0;
+ target += strlen(" to ");
+ strbuf_reset(&cb->buf);
+ hashcpy(cb->nsha1, nsha1);
+ for (end = target; *end && *end != '\n'; end++)
+ ;
+ strbuf_add(&cb->buf, target, end - target);
+ return 0;
+}
+
+static void wt_status_get_detached_from(struct wt_status_state *state)
+{
+ struct grab_1st_switch_cbdata cb;
+ struct commit *commit;
+ unsigned char sha1[20];
+ char *ref = NULL;
+
+ strbuf_init(&cb.buf, 0);
+ if (for_each_recent_reflog_ent("HEAD", grab_1st_switch, 4096, &cb))
+ for_each_reflog_ent("HEAD", grab_1st_switch, &cb);
+ if (!cb.buf.len)
+ return;
+
+ if (dwim_ref(cb.buf.buf, cb.buf.len, sha1, &ref) == 1 &&
+ (commit = lookup_commit_reference_gently(sha1, 1)) != NULL &&
+ !hashcmp(cb.nsha1, commit->object.sha1)) {
+ int ofs;
+ if (!prefixcmp(ref, "refs/tags/"))
+ ofs = strlen("refs/tags/");
+ else if (!prefixcmp(ref, "refs/remotes/"))
+ ofs = strlen("refs/remotes/");
+ else
+ ofs = 0;
+ state->detached_from = xstrdup(ref + ofs);
+ } else
+ state->detached_from =
+ xstrdup(find_unique_abbrev(cb.nsha1, DEFAULT_ABBREV));
+ hashcpy(state->detached_sha1, cb.nsha1);
+
+ free(ref);
+ strbuf_release(&cb.buf);
+}
+
+void wt_status_get_state(struct wt_status_state *state,
+ int get_detached_from)
{
struct strbuf branch = STRBUF_INIT;
struct strbuf onto = STRBUF_INIT;
@@ -1040,6 +1101,10 @@ void wt_status_get_state(struct wt_status_state *state)
read_and_strip_branch(&branch, &state->branch,
"BISECT_START");
}
+
+ if (get_detached_from)
+ wt_status_get_detached_from(state);
+
strbuf_release(&branch);
strbuf_release(&onto);
}
@@ -1066,7 +1131,8 @@ void wt_status_print(struct wt_status *s)
const char *branch_status_color = color(WT_STATUS_HEADER, s);
struct wt_status_state state;
- wt_status_get_state(&state);
+ wt_status_get_state(&state,
+ s->branch && !strcmp(s->branch, "HEAD"));
if (s->branch) {
const char *on_what = _("On branch ");
@@ -1074,9 +1140,19 @@ void wt_status_print(struct wt_status *s)
if (!prefixcmp(branch_name, "refs/heads/"))
branch_name += 11;
else if (!strcmp(branch_name, "HEAD")) {
- branch_name = "";
branch_status_color = color(WT_STATUS_NOBRANCH, s);
- on_what = _("Not currently on any branch.");
+ if (state.detached_from) {
+ unsigned char sha1[20];
+ branch_name = state.detached_from;
+ if (!get_sha1("HEAD", sha1) &&
+ !hashcmp(sha1, state.detached_sha1))
+ on_what = _("HEAD detached at ");
+ else
+ on_what = _("HEAD detached from ");
+ } else {
+ branch_name = "";
+ on_what = _("Not currently on any branch.");
+ }
}
status_printf(s, color(WT_STATUS_HEADER, s), "");
status_printf_more(s, branch_status_color, "%s", on_what);
@@ -1088,6 +1164,7 @@ void wt_status_print(struct wt_status *s)
wt_status_print_state(s, &state);
free(state.branch);
free(state.onto);
+ free(state.detached_from);
if (s->is_initial) {
status_printf_ln(s, color(WT_STATUS_HEADER, s), "");
diff --git a/wt-status.h b/wt-status.h
index 5ddcbf6..5cb7df9 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -81,12 +81,14 @@ struct wt_status_state {
int bisect_in_progress;
char *branch;
char *onto;
+ char *detached_from;
+ unsigned char detached_sha1[20];
};
void wt_status_prepare(struct wt_status *s);
void wt_status_print(struct wt_status *s);
void wt_status_collect(struct wt_status *s);
-void wt_status_get_state(struct wt_status_state *state);
+void wt_status_get_state(struct wt_status_state *state, int get_detached_from);
void wt_shortstatus_print(struct wt_status *s);
void wt_porcelain_print(struct wt_status *s);
--
1.8.1.2.536.gf441e6d
^ permalink raw reply related
* [PATCH v2 2/4] wt-status: move wt_status_get_state() out to wt_status_print()
From: Nguyễn Thái Ngọc Duy @ 2013-03-06 12:21 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Matthieu Moy, Jonathan Niedier,
Nguyễn Thái Ngọc Duy
In-Reply-To: <1362572482-20570-1-git-send-email-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
wt-status.c | 37 +++++++++++++++++++------------------
1 file changed, 19 insertions(+), 18 deletions(-)
diff --git a/wt-status.c b/wt-status.c
index 183aafe..6a3566b 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -1044,31 +1044,29 @@ void wt_status_get_state(struct wt_status_state *state)
strbuf_release(&onto);
}
-static void wt_status_print_state(struct wt_status *s)
+static void wt_status_print_state(struct wt_status *s,
+ struct wt_status_state *state)
{
const char *state_color = color(WT_STATUS_HEADER, s);
- struct wt_status_state state;
-
- wt_status_get_state(&state);
-
- if (state.merge_in_progress)
- show_merge_in_progress(s, &state, state_color);
- else if (state.am_in_progress)
- show_am_in_progress(s, &state, state_color);
- else if (state.rebase_in_progress || state.rebase_interactive_in_progress)
- show_rebase_in_progress(s, &state, state_color);
- else if (state.cherry_pick_in_progress)
- show_cherry_pick_in_progress(s, &state, state_color);
- if (state.bisect_in_progress)
- show_bisect_in_progress(s, &state, state_color);
- free(state.branch);
- free(state.onto);
+ if (state->merge_in_progress)
+ show_merge_in_progress(s, state, state_color);
+ else if (state->am_in_progress)
+ show_am_in_progress(s, state, state_color);
+ else if (state->rebase_in_progress || state->rebase_interactive_in_progress)
+ show_rebase_in_progress(s, state, state_color);
+ else if (state->cherry_pick_in_progress)
+ show_cherry_pick_in_progress(s, state, state_color);
+ if (state->bisect_in_progress)
+ show_bisect_in_progress(s, state, state_color);
}
void wt_status_print(struct wt_status *s)
{
const char *branch_color = color(WT_STATUS_ONBRANCH, s);
const char *branch_status_color = color(WT_STATUS_HEADER, s);
+ struct wt_status_state state;
+
+ wt_status_get_state(&state);
if (s->branch) {
const char *on_what = _("On branch ");
@@ -1087,7 +1085,10 @@ void wt_status_print(struct wt_status *s)
wt_status_print_tracking(s);
}
- wt_status_print_state(s);
+ wt_status_print_state(s, &state);
+ free(state.branch);
+ free(state.onto);
+
if (s->is_initial) {
status_printf_ln(s, color(WT_STATUS_HEADER, s), "");
status_printf_ln(s, color(WT_STATUS_HEADER, s), _("Initial commit"));
--
1.8.1.2.536.gf441e6d
^ permalink raw reply related
* [PATCH v2 1/4] wt-status: split wt_status_state parsing function out
From: Nguyễn Thái Ngọc Duy @ 2013-03-06 12:21 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Matthieu Moy, Jonathan Niedier,
Nguyễn Thái Ngọc Duy
In-Reply-To: <1362572482-20570-1-git-send-email-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
wt-status.c | 52 +++++++++++++++++++++++++++++++---------------------
wt-status.h | 5 +++--
2 files changed, 34 insertions(+), 23 deletions(-)
diff --git a/wt-status.c b/wt-status.c
index ef405d0..183aafe 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -970,7 +970,7 @@ static void show_bisect_in_progress(struct wt_status *s,
* Extract branch information from rebase/bisect
*/
static void read_and_strip_branch(struct strbuf *sb,
- const char **branch,
+ char **branch,
const char *path)
{
unsigned char sha1[20];
@@ -994,52 +994,62 @@ static void read_and_strip_branch(struct strbuf *sb,
strbuf_addstr(sb, abbrev);
*branch = sb->buf;
} else if (!strcmp(sb->buf, "detached HEAD")) /* rebase */
- ;
+ *branch = NULL;
else /* bisect */
*branch = sb->buf;
+ if (*branch)
+ *branch = xstrdup(*branch);
}
-static void wt_status_print_state(struct wt_status *s)
+void wt_status_get_state(struct wt_status_state *state)
{
- const char *state_color = color(WT_STATUS_HEADER, s);
struct strbuf branch = STRBUF_INIT;
struct strbuf onto = STRBUF_INIT;
- struct wt_status_state state;
struct stat st;
- memset(&state, 0, sizeof(state));
+ memset(state, 0, sizeof(*state));
if (!stat(git_path("MERGE_HEAD"), &st)) {
- state.merge_in_progress = 1;
+ state->merge_in_progress = 1;
} else if (!stat(git_path("rebase-apply"), &st)) {
if (!stat(git_path("rebase-apply/applying"), &st)) {
- state.am_in_progress = 1;
+ state->am_in_progress = 1;
if (!stat(git_path("rebase-apply/patch"), &st) && !st.st_size)
- state.am_empty_patch = 1;
+ state->am_empty_patch = 1;
} else {
- state.rebase_in_progress = 1;
- read_and_strip_branch(&branch, &state.branch,
+ state->rebase_in_progress = 1;
+ read_and_strip_branch(&branch, &state->branch,
"rebase-apply/head-name");
- read_and_strip_branch(&onto, &state.onto,
+ read_and_strip_branch(&onto, &state->onto,
"rebase-apply/onto");
}
} else if (!stat(git_path("rebase-merge"), &st)) {
if (!stat(git_path("rebase-merge/interactive"), &st))
- state.rebase_interactive_in_progress = 1;
+ state->rebase_interactive_in_progress = 1;
else
- state.rebase_in_progress = 1;
- read_and_strip_branch(&branch, &state.branch,
+ state->rebase_in_progress = 1;
+ read_and_strip_branch(&branch, &state->branch,
"rebase-merge/head-name");
- read_and_strip_branch(&onto, &state.onto,
+ read_and_strip_branch(&onto, &state->onto,
"rebase-merge/onto");
} else if (!stat(git_path("CHERRY_PICK_HEAD"), &st)) {
- state.cherry_pick_in_progress = 1;
+ state->cherry_pick_in_progress = 1;
}
if (!stat(git_path("BISECT_LOG"), &st)) {
- state.bisect_in_progress = 1;
- read_and_strip_branch(&branch, &state.branch,
+ state->bisect_in_progress = 1;
+ read_and_strip_branch(&branch, &state->branch,
"BISECT_START");
}
+ strbuf_release(&branch);
+ strbuf_release(&onto);
+}
+
+static void wt_status_print_state(struct wt_status *s)
+{
+ const char *state_color = color(WT_STATUS_HEADER, s);
+ struct wt_status_state state;
+
+ wt_status_get_state(&state);
if (state.merge_in_progress)
show_merge_in_progress(s, &state, state_color);
@@ -1051,8 +1061,8 @@ static void wt_status_print_state(struct wt_status *s)
show_cherry_pick_in_progress(s, &state, state_color);
if (state.bisect_in_progress)
show_bisect_in_progress(s, &state, state_color);
- strbuf_release(&branch);
- strbuf_release(&onto);
+ free(state.branch);
+ free(state.onto);
}
void wt_status_print(struct wt_status *s)
diff --git a/wt-status.h b/wt-status.h
index 81e1dcf..5ddcbf6 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -79,13 +79,14 @@ struct wt_status_state {
int rebase_interactive_in_progress;
int cherry_pick_in_progress;
int bisect_in_progress;
- const char *branch;
- const char *onto;
+ char *branch;
+ char *onto;
};
void wt_status_prepare(struct wt_status *s);
void wt_status_print(struct wt_status *s);
void wt_status_collect(struct wt_status *s);
+void wt_status_get_state(struct wt_status_state *state);
void wt_shortstatus_print(struct wt_status *s);
void wt_porcelain_print(struct wt_status *s);
--
1.8.1.2.536.gf441e6d
^ permalink raw reply related
* [PATCH v2 0/4] nd/branch-show-rebase-bisect-state updates
From: Nguyễn Thái Ngọc Duy @ 2013-03-06 12:21 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Matthieu Moy, Jonathan Niedier,
Nguyễn Thái Ngọc Duy
In-Reply-To: <1362303681-6585-1-git-send-email-pclouds@gmail.com>
Since the previous round:
- reflog format change is dropped
- almost always show "HEAD detached from/at xxx" instead of
"currently not on any branch", where "xxx" is either a ref, or an
abbreviated sha-1
I wanted to introduce something like @{-1:to} that resolves the "to"
sha-1 in reflog, in addition to @{-1} which resolves the "from" part.
But the syntax looks ugly so I dropped it. Meanwhile people could do
git log -1 -g --grep-reflog checkout --pretty=format:%h
to retrieve the same info.
Nguyễn Thái Ngọc Duy (4):
wt-status: split wt_status_state parsing function out
wt-status: move wt_status_get_state() out to wt_status_print()
status: show more info than "currently not on any branch"
branch: show more information when HEAD is detached
builtin/branch.c | 25 +++++++-
t/t3203-branch-output.sh | 6 +-
t/t6030-bisect-porcelain.sh | 2 +-
t/t7406-submodule-update.sh | 6 +-
t/t7512-status-help.sh | 52 +++++++++------
wt-status.c | 152 ++++++++++++++++++++++++++++++++++----------
wt-status.h | 7 +-
7 files changed, 190 insertions(+), 60 deletions(-)
--
1.8.1.2.536.gf441e6d
^ permalink raw reply
* [PATCH] format-patch: RFC 2047 says multi-octet character may not be split
From: Kirill Smelkov @ 2013-03-06 11:08 UTC (permalink / raw)
To: Junio C Hamano
Cc: Dmitry Komissarov, git, Kirill Smelkov, Jan H. Schönherr
Intro
-----
In 'Subject:' characters are encoded in Q encoding, as per RFC 2047, e.g.
föö
becomes
=?UTF-8?q?f=C3=B6=C3=B6?=
. Long encoded lines must be wrapped to be no longer than 76 bytes.
Also RFC 2047, section 5 (3) says:
Each 'encoded-word' MUST represent an integral number of
characters. A multi-octet character may not be split across
adjacent 'encoded- word's.
that means that for
Subject: .... föö bar
encoding
Subject: =?UTF-8?q?....=20f=C3=B6=C3=B6?=
=?UTF-8?q?=20bar?=
is correct, and
Subject: =?UTF-8?q?....=20f=C3=B6=C3?= <-- NOTE ö is broken here
=?UTF-8?q?=B6=20bar?=
is not, because "ö" character UTF-8 encoding C3 B6 is split here across
adjacent encoded words.
~~~~
As it is now, format-patch does not respect "multi-octet charactes may
not be split" rule, and so sending patches with non-english subject has
issues:
The problematic case shows in mail readers as ".... fö?? bar".
Solution
--------
I introduce mbs_chrlen() function to compute character length in bytes
for multi-byte text according to encoding, and use it appropriately in
add_rfc2047() in pretty.
So far it works correctly only for UTF-8 encoding, because we have
infrastructure for it in place already, but other encoding could be
supported too in the future with the help of iconv. For now they all, except
UTF-8, are treated as being one-byte encodings, which was format-patch
current behaviour, with appropriate TODO put in mbs_chrlen().
Not sure whether mbs_chrlen() is a good name, but otherwise my
understanding is that the patch is ok to go in.
Thanks.
Cc: Jan H. Schönherr <schnhrr@cs.tu-berlin.de>
Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru>
---
pretty.c | 27 +++++++++++++++++++--------
t/t4014-format-patch.sh | 27 ++++++++++++++-------------
utf8.c | 39 +++++++++++++++++++++++++++++++++++++++
utf8.h | 2 ++
4 files changed, 74 insertions(+), 21 deletions(-)
diff --git a/pretty.c b/pretty.c
index b57adef..c9c7ff5 100644
--- a/pretty.c
+++ b/pretty.c
@@ -345,7 +345,7 @@ static int needs_rfc2047_encoding(const char *line, int len,
return 0;
}
-static void add_rfc2047(struct strbuf *sb, const char *line, int len,
+static void add_rfc2047(struct strbuf *sb, const char *line, size_t len,
const char *encoding, enum rfc2047_type type)
{
static const int max_encoded_length = 76; /* per rfc2047 */
@@ -355,9 +355,18 @@ static void add_rfc2047(struct strbuf *sb, const char *line, int len,
strbuf_grow(sb, len * 3 + strlen(encoding) + 100);
strbuf_addf(sb, "=?%s?q?", encoding);
line_len += strlen(encoding) + 5; /* 5 for =??q? */
- for (i = 0; i < len; i++) {
- unsigned ch = line[i] & 0xFF;
- int is_special = is_rfc2047_special(ch, type);
+
+ while (len) {
+ /*
+ * RFC 2047, section 5 (3):
+ *
+ * Each 'encoded-word' MUST represent an integral number of
+ * characters. A multi-octet character may not be split across
+ * adjacent 'encoded- word's.
+ */
+ const unsigned char *p = (const unsigned char *)line;
+ int chrlen = mbs_chrlen(&line, &len, encoding);
+ int is_special = (chrlen > 1) || is_rfc2047_special(*p, type);
/*
* According to RFC 2047, we could encode the special character
@@ -367,16 +376,18 @@ static void add_rfc2047(struct strbuf *sb, const char *line, int len,
* causes ' ' to be encoded as '=20', avoiding this problem.
*/
- if (line_len + 2 + (is_special ? 3 : 1) > max_encoded_length) {
+ if (line_len + 2 + (is_special ? 3*chrlen : 1) > max_encoded_length) {
strbuf_addf(sb, "?=\n =?%s?q?", encoding);
line_len = strlen(encoding) + 5 + 1; /* =??q? plus SP */
}
if (is_special) {
- strbuf_addf(sb, "=%02X", ch);
- line_len += 3;
+ for (i = 0; i < chrlen; i++) {
+ strbuf_addf(sb, "=%02X", p[i]);
+ line_len += 3;
+ }
} else {
- strbuf_addch(sb, ch);
+ strbuf_addch(sb, *p);
line_len++;
}
}
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index 78633cb..b993dae 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -837,25 +837,26 @@ Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
=?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
=?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
=?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
- =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3?=
- =?UTF-8?q?=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
- =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3?=
- =?UTF-8?q?=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
+ =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
=?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
=?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
=?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
- =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3?=
- =?UTF-8?q?=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
- =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3?=
- =?UTF-8?q?=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
+ =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
=?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
=?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
=?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
- =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3?=
- =?UTF-8?q?=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
- =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3?=
- =?UTF-8?q?=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
- =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
+ =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
+ =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
+ =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
+ =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
+ =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
+ =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
+ =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
+ =?UTF-8?q?bar?=
EOF
test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
rm -rf patches/ &&
diff --git a/utf8.c b/utf8.c
index 8f6e84b..7911b58 100644
--- a/utf8.c
+++ b/utf8.c
@@ -531,3 +531,42 @@ char *reencode_string(const char *in, const char *out_encoding, const char *in_e
return out;
}
#endif
+
+/*
+ * Returns first character length in bytes for multi-byte `text` according to
+ * `encoding`.
+ *
+ * - The `text` pointer is updated to point at the next character.
+ * - When `remainder_p` is not NULL, on entry `*remainder_p` is how much bytes
+ * we can consume from text, and on exit `*remainder_p` is reduced by returned
+ * character length. Otherwise `text` is treated as limited by NUL.
+ */
+int mbs_chrlen(const char **text, size_t *remainder_p, const char *encoding)
+{
+ int chrlen;
+ const char *p = *text;
+ size_t r = (remainder_p ? *remainder_p : INT_MAX);
+
+ if (r < 1)
+ return 0;
+
+ if (is_encoding_utf8(encoding)) {
+ pick_one_utf8_char(&p, &r);
+
+ chrlen = p ? (p - *text)
+ : 1 /* not valid UTF-8 -> raw byte sequence */;
+ }
+ else {
+ /* TODO use iconv to decode one char and obtain its chrlen
+ *
+ * for now, let's treat encodings != UTF-8 as one-byte
+ */
+ chrlen = 1;
+ }
+
+ *text += chrlen;
+ if (remainder_p)
+ *remainder_p -= chrlen;
+
+ return chrlen;
+}
diff --git a/utf8.h b/utf8.h
index 501b2bd..1f8ecad 100644
--- a/utf8.h
+++ b/utf8.h
@@ -22,4 +22,6 @@ char *reencode_string(const char *in, const char *out_encoding, const char *in_e
#define reencode_string(a,b,c) NULL
#endif
+int mbs_chrlen(const char **text, size_t *remainder_p, const char *encoding);
+
#endif
--
1.8.2.rc2.353.gd2380b4
^ permalink raw reply related
* Re: Using socks proxy with git for http(s) transport
From: Daniel Stenberg @ 2013-03-06 10:39 UTC (permalink / raw)
To: Yves Blusseau; +Cc: Jeff King, git
In-Reply-To: <CABmRxH25y9bAdZWV_3MG7x2LNGNDQbLB_EJC1xAJC396nO7bYQ@mail.gmail.com>
On Wed, 6 Mar 2013, Yves Blusseau wrote:
> I have try with an old version of curl: 7.15.5 and with the latest in
> development curl 7.29.1-DEV. But it seem that git-remote-http is compile
> with the old one.
libcurl 7.15.5 is over 6 years old.
The support for "socks[*]://" prefixes in proxy names was added to libcurl
7.21.7 (June 23 2011).
--
/ daniel.haxx.se
^ permalink raw reply
* feature suggestion: improve rerere
From: Uwe Kleine-König @ 2013-03-06 10:16 UTC (permalink / raw)
To: git; +Cc: kernel
Hello,
I think the following suggestion is sound. And it might even be easy to
implement but I don't know how rerere works, so I might be wrong here.
When applying a patch it's normal to hit a conflict. For me this just
happend:
$ git diff
diff --cc flash_otp_write.c
index f360a3e,648e042..0000000
--- a/flash_otp_write.c
+++ b/flash_otp_write.c
@@@ -15,8 -15,23 +15,29 @@@
#include <mtd/mtd-user.h>
++<<<<<<< ours
+#include "common.h"
+
++||||||| base
++=======
+ ssize_t xread(int fd, void *buf, size_t count)
+ {
+ ssize_t ret, done = 0;
+
+ retry:
+ ret = read(fd, buf + done, count - done);
+ if (ret < 0)
+ return ret;
+
+ done += ret;
+
+ if (ret == 0 /* EOF */ || done == count)
+ return done;
+ else
+ goto retry;
+ }
+
++>>>>>>> theirs
int main(int argc,char *argv[])
{
int fd, val, ret, size, wrote, len;
easy to resolve to:
$ git diff
diff --cc flash_otp_write.c
index f360a3e,648e042..0000000
--- a/flash_otp_write.c
+++ b/flash_otp_write.c
@@@ -15,8 -15,23 +15,25 @@@
#include <mtd/mtd-user.h>
+#include "common.h"
+
+ ssize_t xread(int fd, void *buf, size_t count)
+ {
+ ssize_t ret, done = 0;
+
+ retry:
+ ret = read(fd, buf + done, count - done);
+ if (ret < 0)
+ return ret;
+
+ done += ret;
+
+ if (ret == 0 /* EOF */ || done == count)
+ return done;
+ else
+ goto retry;
+ }
+
int main(int argc,char *argv[])
{
int fd, val, ret, size, wrote, len;
Now if I shuffle patches and put the new patch before the conflicting
patch, I have to resolve first:
$ git diff
diff --cc flash_otp_write.c
index d407ebb,31b963e..0000000
--- a/flash_otp_write.c
+++ b/flash_otp_write.c
@@@ -15,6 -15,25 +15,31 @@@
#include <mtd/mtd-user.h>
++<<<<<<< ours
++||||||| base
++#include "common.h"
++
++=======
+ #include "common.h"
+
+ ssize_t xread(int fd, void *buf, size_t count)
+ {
+ ssize_t ret, done = 0;
+
+ retry:
+ ret = read(fd, buf + done, count - done);
+ if (ret < 0)
+ return ret;
+
+ done += ret;
+
+ if (ret == 0 /* EOF */ || done == count)
+ return done;
+ else
+ goto retry;
+ }
+
++>>>>>>> theirs
int main(int argc,char *argv[])
{
int fd, val, ret, size, wrote, len;
which is resolved to just adding the function and dropping the #include.
But then readding the 2nd patch it conflicts again:
$ git diff
diff --cc flash_otp_write.c
index 648e042,f360a3e..0000000
--- a/flash_otp_write.c
+++ b/flash_otp_write.c
@@@ -15,23 -15,8 +15,29 @@@
#include <mtd/mtd-user.h>
++<<<<<<< ours
+ssize_t xread(int fd, void *buf, size_t count)
+{
+ ssize_t ret, done = 0;
+
+retry:
+ ret = read(fd, buf + done, count - done);
+ if (ret < 0)
+ return ret;
+
+ done += ret;
+
+ if (ret == 0 /* EOF */ || done == count)
+ return done;
+ else
+ goto retry;
+}
+
++||||||| base
++=======
+ #include "common.h"
+
++>>>>>>> theirs
int main(int argc,char *argv[])
{
int fd, val, ret, size, wrote, len;
This is the same conflict as the first one, just with ours and theirs
exchanged. So my suggestion is to make rerere use the resolution
recorded for the first conflict here.
Sounds sensible?
Best regards
Uwe
PS: I'm using Debian's git 1.8.2~rc2-1 and hope I didn't miss this
feature already implemented while looking through v1.8.2..junio/next.
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
* Re: Using socks proxy with git for http(s) transport
From: Yves Blusseau @ 2013-03-06 10:09 UTC (permalink / raw)
To: Jeff King; +Cc: git
In-Reply-To: <20130306094552.GA11531@sigill.intra.peff.net>
2013/3/6 Jeff King <peff@peff.net>:
> On Wed, Mar 06, 2013 at 10:21:42AM +0100, Yves Blusseau wrote:
>
>> > Try:
>> >
>> > git config --global http.proxy 'socks://yourhost:port'
>> >
>> > That will enable it for all git repositories on your machine. Git should
>> > also respect any environment variables that curl handles (because we use
>> > libcurl under the hood), if you prefer to set it up that way. See "man
>> > curl" for details.
>>
>> Thanks Jeff but it's not working.
>
> Hmm. I just double-checked, and it works for me.
>
>> I use git 1.8.15
>
> I assume you mean 1.8.1.5 here.
Yes it's 1.8.15 sorry for the mistake
>
>> My socks proxy listen on my localhost at port 1080 so I do:
>> git config --global http.proxy 'socks://127.0.0.1:1080'
>
> That looks right to me.
>
>> But when i try to talk with a git server with http protocol i have:
>> [...]
>> * About to connect() to proxy 127.0.0.1 port 1080
>> * Trying 127.0.0.1... * connected
>> * Connected to 127.0.0.1 (127.0.0.1) port 1080
>> > GET http://git.kernel.org/pub/scm/git/git.git/info/refs?service=git-upload-pack HTTP/1.1
>> [...]
>> * Empty reply from server
>
> If I set up a simple socks proxy with ssh, like:
>
> ssh -v -D 1080 my-ssh-host
My socks proxy is also a socks proxy with ssh
>
> and run the same command, I get:
>
> * About to connect() to proxy localhost port 1080 (#0)
> * Trying 127.0.0.1...
> * SOCKS4 request granted.
> * Connected to localhost (127.0.0.1) port 1080 (#0)
> > GET /pub/scm/git/git.git/info/refs?service=git-upload-pack HTTP/1.1
> [...]
> < HTTP/1.1 200 OK
You have a (#0) in the log that i have when using curl directly with
the socks proxy
>
> and it works. It does look like curl is treating localhost:1080 as a
> regular http proxy. What version of libcurl do you have? Is there
> anything in your environment that might be causing it to override the
> configured proxy setting (e.g., an http_proxy or https_proxy environment
> variable)?
I have try with an old version of curl: 7.15.5 and with the latest in
development curl 7.29.1-DEV.
But it seem that git-remote-http is compile with the old one.
I have no http/proxy environment variables
^ permalink raw reply
* Re: Using socks proxy with git for http(s) transport
From: Jeff King @ 2013-03-06 9:45 UTC (permalink / raw)
To: Yves Blusseau; +Cc: git
In-Reply-To: <CABmRxH2CGTxFaGufSMgUqhrSTZPvFBHoEnP8-p5HhkU4kszJPw@mail.gmail.com>
On Wed, Mar 06, 2013 at 10:21:42AM +0100, Yves Blusseau wrote:
> > Try:
> >
> > git config --global http.proxy 'socks://yourhost:port'
> >
> > That will enable it for all git repositories on your machine. Git should
> > also respect any environment variables that curl handles (because we use
> > libcurl under the hood), if you prefer to set it up that way. See "man
> > curl" for details.
>
> Thanks Jeff but it's not working.
Hmm. I just double-checked, and it works for me.
> I use git 1.8.15
I assume you mean 1.8.1.5 here.
> My socks proxy listen on my localhost at port 1080 so I do:
> git config --global http.proxy 'socks://127.0.0.1:1080'
That looks right to me.
> But when i try to talk with a git server with http protocol i have:
> [...]
> * About to connect() to proxy 127.0.0.1 port 1080
> * Trying 127.0.0.1... * connected
> * Connected to 127.0.0.1 (127.0.0.1) port 1080
> > GET http://git.kernel.org/pub/scm/git/git.git/info/refs?service=git-upload-pack HTTP/1.1
> [...]
> * Empty reply from server
If I set up a simple socks proxy with ssh, like:
ssh -v -D 1080 my-ssh-host
and run the same command, I get:
* About to connect() to proxy localhost port 1080 (#0)
* Trying 127.0.0.1...
* SOCKS4 request granted.
* Connected to localhost (127.0.0.1) port 1080 (#0)
> GET /pub/scm/git/git.git/info/refs?service=git-upload-pack HTTP/1.1
[...]
< HTTP/1.1 200 OK
and it works. It does look like curl is treating localhost:1080 as a
regular http proxy. What version of libcurl do you have? Is there
anything in your environment that might be causing it to override the
configured proxy setting (e.g., an http_proxy or https_proxy environment
variable)?
> As you can see git connect to my socks proxy (Connected to 127.0.0.1
> (127.0.0.1) port 1080) but seems to send the http request directly
> instead of a socks command. So it does'nt work :(
Yeah, that definitely looks like the problem.
-Peff
^ permalink raw reply
* Re: Using socks proxy with git for http(s) transport
From: Yves Blusseau @ 2013-03-06 9:35 UTC (permalink / raw)
To: Jeff King; +Cc: git
In-Reply-To: <20130306082110.GA31638@sigill.intra.peff.net>
2013/3/6 Jeff King <peff@peff.net>:
> Try:
>
> git config --global http.proxy 'socks://yourhost:port'
>
> That will enable it for all git repositories on your machine. Git should
> also respect any environment variables that curl handles (because we use
> libcurl under the hood), if you prefer to set it up that way. See "man
> curl" for details.
>
> -Peff
Also try setting ALL_PROXY environment variable that curl handle:
export ALL_PROXY='socks5://127.0.0.1:1080'
Work with curl:
curl -v http://git.kernel.org/pub/scm/git/git.git/info/refs?service=git-upload-pack
* About to connect() to proxy 127.0.0.1 port 1080 (#0)
* Trying 127.0.0.1...
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:--
--:--:-- 0* 198
* 145
* 20
* 140
* Connected to 127.0.0.1 (127.0.0.1) port 1080 (#0)
> GET /pub/scm/git/git.git/info/refs?service=git-upload-pack HTTP/1.1
> User-Agent: curl/7.29.1-DEV
> Host: git.kernel.org
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx
< Date: Wed, 06 Mar 2013 09:33:05 GMT
< Content-Type: application/x-git-upload-pack-advertisement
< Transfer-Encoding: chunked
< Connection: keep-alive
< Expires: Fri, 01 Jan 1980 00:00:00 GMT
< Pragma: no-cache
< Cache-Control: no-cache, max-age=0, must-revalidate
<
{ [data not shown]
But with git (without the http.proxy configuration in .gitconfig):
GIT_TRACE=1 GIT_CURL_VERBOSE=1 git clone
http://git.kernel.org/pub/scm/git/git.git
trace: built-in: git 'clone' 'http://git.kernel.org/pub/scm/git/git.git'
Cloning into 'git'...
trace: run_command: 'git-remote-http' 'origin'
'http://git.kernel.org/pub/scm/git/git.git'
* Couldn't find host git.kernel.org in the .netrc file, using defaults
* About to connect() to proxy 127.0.0.1 port 1080
* Trying 127.0.0.1... * connected
* Connected to 127.0.0.1 (127.0.0.1) port 1080
> GET http://git.kernel.org/pub/scm/git/git.git/info/refs?service=git-upload-pack HTTP/1.1
User-Agent: git/1.8.1.5
Host: git.kernel.org
Accept: */*
Accept-Encoding: gzip
Proxy-Connection: Keep-Alive
Pragma: no-cache
* Empty reply from server
* Connection #0 to host 127.0.0.1 left intact
error: Empty reply from server while accessing
http://git.kernel.org/pub/scm/git/git.git/info/refs?service=git-upload-pack
fatal: HTTP request failed
Regards,
Yves
^ permalink raw reply
* Re: Using socks proxy with git for http(s) transport
From: Yves Blusseau @ 2013-03-06 9:21 UTC (permalink / raw)
To: git
In-Reply-To: <20130306082110.GA31638@sigill.intra.peff.net>
> Try:
>
> git config --global http.proxy 'socks://yourhost:port'
>
> That will enable it for all git repositories on your machine. Git should
> also respect any environment variables that curl handles (because we use
> libcurl under the hood), if you prefer to set it up that way. See "man
> curl" for details.
Thanks Jeff but it's not working.
I use git 1.8.15
My socks proxy listen on my localhost at port 1080 so I do:
git config --global http.proxy 'socks://127.0.0.1:1080'
But when i try to talk with a git server with http protocol i have:
GIT_TRACE=1 GIT_CURL_VERBOSE=1 git ls-remote
http://git.kernel.org/pub/scm/git/git.git
trace: built-in: git 'ls-remote' 'http://git.kernel.org/pub/scm/git/git.git'
trace: run_command: 'git-remote-http'
'http://git.kernel.org/pub/scm/git/git.git'
'http://git.kernel.org/pub/scm/git/git.git'
* Couldn't find host git.kernel.org in the .netrc file, using defaults
* About to connect() to proxy 127.0.0.1 port 1080
* Trying 127.0.0.1... * connected
* Connected to 127.0.0.1 (127.0.0.1) port 1080
> GET http://git.kernel.org/pub/scm/git/git.git/info/refs?service=git-upload-pack HTTP/1.1
User-Agent: git/1.8.1.5
Host: git.kernel.org
Accept: */*
Accept-Encoding: gzip
Proxy-Connection: Keep-Alive
Pragma: no-cache
* Empty reply from server
* Connection #0 to host 127.0.0.1 left intact
error: Empty reply from server while accessing
http://git.kernel.org/pub/scm/git/git.git/info/refs?service=git-upload-pack
fatal: HTTP request failed
As you can see git connect to my socks proxy (Connected to 127.0.0.1
(127.0.0.1) port 1080) but seems to send the http request directly
instead of a socks command. So it does'nt work :(
Regards,
Yves
^ permalink raw reply
* Re: auto merge bug
From: Jeff King @ 2013-03-06 9:15 UTC (permalink / raw)
To: David Krmpotic; +Cc: Junio C Hamano, git
In-Reply-To: <CAOFaZ+4oUD7eMvFmtPdca4AYooxW-PCOiPBUb0jjVw4LPBN8+Q@mail.gmail.com>
On Tue, Mar 05, 2013 at 11:13:12PM +0100, David Krmpotic wrote:
> Hi guys! Thank you for responses.. I haven't suspected that repos
> created via GitHub windows app would have union set by default :( have
> to ask them about it.. it seems wrong to me… Here are the defaults for
> a windows repo created with GitHub for windows app:
> [...]
> # Custom for Visual Studio
> *.cs diff=csharp
> *.sln merge=union
> *.csproj merge=union
> *.vbproj merge=union
> *.fsproj merge=union
> *.dbproj merge=union
Yeah, I think defaulting to merge=union there is questionable. In an
ideal world, the GitHub for Windows folks would ship a specialized merge
helper for handling VS project files. It can be open-source and
distributed separately for people who don't use GitHub, but they can
integrate it seamlessly into the GitHub client. So everybody wins.
I see you've already written to GitHub support; thanks. I'll make sure
your issue gets routed to the right people, and I'll see if I can
convince them to write the specialized tool. :)
-Peff
^ permalink raw reply
* Re: [PATCH v2 0/4] push --follow-tags
From: Jeff King @ 2013-03-06 8:41 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <1362523639-30566-1-git-send-email-gitster@pobox.com>
On Tue, Mar 05, 2013 at 02:47:15PM -0800, Junio C Hamano wrote:
> The primary change since the last round is that it pushes out only
> annotated tags that are missing from the other side.
Like you, I have mixed feelings on treating annotated tags separately. I
don't feel like the previous discussion actually came to a conclusion.
I kind of lean towards the "if we are pushing A..B to a ref, no matter
if the remote had the objects already, consider any tag that peels to
any commit in A..B". That seems intuitive to me, and reduces the chances
of accidentally pushing crufty tags. But I admit it's just a gut
feeling.
I think the implementation would just be something like:
for each ref we are pushing
mark ref->old_sha1 as UNINTERESTING
add ref->new_sha1 to pending
traverse pending commits, marking SEEN
for each local tag
if tag does not exist on remote &&
commit = lookup_commit_reference_gently(tag) &&
commit->object.flags & SEEN
push tag
-Peff
^ permalink raw reply
* Re: [PATCH v2 1/4] commit.c: add clear_commit_marks_many()
From: Jeff King @ 2013-03-06 8:30 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <1362523639-30566-2-git-send-email-gitster@pobox.com>
On Tue, Mar 05, 2013 at 02:47:16PM -0800, Junio C Hamano wrote:
> clear_commit_marks(struct commit *, unsigned) only can clear flag
> bits starting from a single commit; introduce an API to allow
> feeding an array of commits, so that flag bits can be cleared from
> commits reachable from any of them with a single traversal.
Out of curiosity, is that actually measurably more efficient?
Since we stop traversing a commit's parents when we see it does not have
any of the flags we are clearing, we should visit most commits once. The
exception is ones that we hit by multiple paths. But that should
be the same whether it is done as part of a single traversal or
multiple; in each case, we hit the commit and say "Oh, already cleared;
do not add it to the parents list".
So I would expect it to have little to no impact on performance. I
still think it is a sane interface change; I was just curious from the
commit message whether there could be a performance impact.
-Peff
^ permalink raw reply
* Re: [PATCH] Extend runtime prefix computation
From: Michael Weiser @ 2013-03-06 8:19 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vd2vdvn7l.fsf@alter.siamese.dyndns.org>
Hello Junio,
On Tue, Mar 05, 2013 at 08:13:50AM -0800, Junio C Hamano wrote:
> >> Support determining the binaries' installation path at runtime even if
> >> called without any path components (i.e. via search path).
> The default for any change is not to include it. Is there any
> reason why we want this change?
It makes a binary git installation fully relocatable. Seeing how git
already has basic support for it I thought other people might be
interested in this.
Thanks,
--
Michael Weiser science + computing ag
Senior Systems Engineer Geschaeftsstelle Duesseldorf
Martinstrasse 47-55, Haus A
phone: +49 211 302 708 32 D-40223 Duesseldorf
fax: +49 211 302 708 50 www.science-computing.de
--
Vorstandsvorsitzender/Chairman of the board of management:
Gerd-Lothar Leonhart
Vorstand/Board of Management:
Dr. Bernd Finkbeiner, Michael Heinrichs,
Dr. Arno Steitz, Dr. Ingrid Zech
Vorsitzender des Aufsichtsrats/
Chairman of the Supervisory Board:
Philippe Miltin
Sitz/Registered Office: Tuebingen
Registergericht/Registration Court: Stuttgart
Registernummer/Commercial Register No.: HRB 382196
^ permalink raw reply
* Re: Using socks proxy with git for http(s) transport
From: Jeff King @ 2013-03-06 8:21 UTC (permalink / raw)
To: Yves Blusseau; +Cc: git
In-Reply-To: <CABmRxH1g2BR+-MvGZ4J-2vC8NDq3x8pG148hXfuYTpUkX0L=0A@mail.gmail.com>
On Wed, Mar 06, 2013 at 09:12:30AM +0100, Yves Blusseau wrote:
> i have a socks proxy to access internet.
> I successed in configuring git (with GIT_PROXY_COMMAND) to use the
> socks proxy for GIT transport protocol.
> But how to use this socks proxy with git for HTTP(S) transport protocol ?
Try:
git config --global http.proxy 'socks://yourhost:port'
That will enable it for all git repositories on your machine. Git should
also respect any environment variables that curl handles (because we use
libcurl under the hood), if you prefer to set it up that way. See "man
curl" for details.
-Peff
^ permalink raw reply
* Using socks proxy with git for http(s) transport
From: Yves Blusseau @ 2013-03-06 8:12 UTC (permalink / raw)
To: git
Hi all,
i have a socks proxy to access internet.
I successed in configuring git (with GIT_PROXY_COMMAND) to use the
socks proxy for GIT transport protocol.
But how to use this socks proxy with git for HTTP(S) transport protocol ?
Best Regards,
Yves
^ permalink raw reply
* [PATCH] add: Clarify documentation of -A and -u
From: Greg Price @ 2013-03-06 7:26 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
The documentation of '-A' is very confusing for someone who doesn't
already know what it does. In particular, it describes the option's
meaning by reference to that of '-u', but it's no more similar to the
latter than it is to the default behavior. Describe it directly (and
in a way that uses the word 'all'), and then describe the contrast
separately.
Signed-off-by: Greg Price <price@mit.edu>
---
Documentation/git-add.txt | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
index 388a225..f89d920 100644
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -105,7 +105,9 @@ apply to the index. See EDITING PATCHES below.
will never stage new files, but that it will stage modified
new contents of tracked files and that it will remove files
from the index if the corresponding files in the working tree
- have been removed.
+ have been removed. By contrast `-A` will add new files as
+ well as updating and removing existing ones, and the default
+ behavior will add new files and will not remove existing ones.
+
If no <pathspec> is given, the current version of Git defaults to
"."; in other words, update all tracked files in the current directory
@@ -114,10 +116,17 @@ of Git, hence the form without <pathspec> should not be used.
-A::
--all::
- Like `-u`, but match <pathspec> against files in the
- working tree in addition to the index. That means that it
- will find new files as well as staging modified content and
- removing files that are no longer in the working tree.
+ Update the index regarding all files that match <pathspec>,
+ either in the index or the working tree. That is, remove
+ files that are only in the index, add files that are only in
+ the working tree, and update files that differ between the
+ two. By contrast `-u` only removes and updates, and the
+ default behavior only adds and updates.
++
+If no <pathspec> is given, the current version of Git defaults to
+"."; in other words, update all tracked files in the current directory
+and its subdirectories. This default will change in a future version
+of Git, hence the form without <pathspec> should not be used.
-N::
--intent-to-add::
--
1.7.11.3
^ permalink raw reply related
* [PATCH] add: cut redundant require_pathspec logic
From: Greg Price @ 2013-03-06 7:24 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
If take_worktree_changes is true, then the logic around
option_with_implicit_dot ensures argc is positive by this point.
So require_pathspec never has an effect.
Signed-off-by: Greg Price <price@mit.edu>
---
builtin/add.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/builtin/add.c b/builtin/add.c
index 0dd014e..9feb2ba 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -358,7 +358,6 @@ int cmd_add(int argc, const char **argv, const char *prefix)
struct dir_struct dir;
int flags;
int add_new_files;
- int require_pathspec;
char *seen = NULL;
const char *option_with_implicit_dot = NULL;
const char *short_option_with_implicit_dot = NULL;
@@ -399,7 +398,6 @@ int cmd_add(int argc, const char **argv, const char *prefix)
}
add_new_files = !take_worktree_changes && !refresh_only;
- require_pathspec = !take_worktree_changes;
newfd = hold_locked_index(&lock_file, 1);
@@ -410,7 +408,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
(!(addremove || take_worktree_changes)
? ADD_CACHE_IGNORE_REMOVAL : 0));
- if (require_pathspec && argc == 0) {
+ if (argc == 0) {
fprintf(stderr, _("Nothing specified, nothing added.\n"));
fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n"));
return 0;
--
1.7.11.3
^ permalink raw reply related
* Re: [PATCH v6] submodule: add 'deinit' command
From: Heiko Voigt @ 2013-03-06 6:52 UTC (permalink / raw)
To: Junio C Hamano
Cc: Jens Lehmann, Phil Hord, Git Mailing List, Michael J Gruber,
Marc Branchaud, W. Trevor King
In-Reply-To: <7vppzdvoj1.fsf@alter.siamese.dyndns.org>
On Tue, Mar 05, 2013 at 07:45:22AM -0800, Junio C Hamano wrote:
> Heiko Voigt <hvoigt@hvoigt.net> writes:
>
> >> + if test -z "$force"
> >> + then
> >> + git rm -n "$sm_path" ||
> >> + die "$(eval_gettext "Submodule work tree '\$sm_path' contains local modifications; use '-f' to discard them")"
> >
> > Minor nit. IMO, there is an indentation for the || missing here. Maybe
> > Junio can squash that in on his side?
>
> Sorry, but I do not see an indentation nit here. The format looks
> perfectly sane to me and in fact any other indentation would be
> wrong.
>
> Puzzled...
Wouldn't you write this code snippet like this to make clear that there
is another conditional?
if test -z "$force"
then
git rm -n "$sm_path" ||
die "$(eval_gettext "Submodule work tree '\$sm_path' contains local modifications; use '-f' to discard them")"
It seems it is not clear in the code base either. Some places do
some do not indent:
git grep -A 1 '||' *.sh
Except for the testsuite I just assumed that this style was common,
because for me it makes the code much easier to read.
It seems it is not, so forget my comment.
Cheers Heiko
^ permalink raw reply
* Re: "git rebase" loses the additional changes in "evil" merges
From: Junio C Hamano @ 2013-03-05 23:31 UTC (permalink / raw)
To: Philip Oakley; +Cc: Dale Worley, Git List
In-Reply-To: <D9E55432793A444F941789A493F97B1C@PhilipOakley>
"Philip Oakley" <philipoakley@iee.org> writes:
> Given that many folk appear to trip up with their rebase mindset, does
> this suggest that a few tweaks to the manual may be in order to stop
> such misunderstandings?
Perhaps.
^ permalink raw reply
* Re: "git rebase" loses the additional changes in "evil" merges
From: Philip Oakley @ 2013-03-05 23:16 UTC (permalink / raw)
To: Junio C Hamano, Dale Worley; +Cc: Git List
In-Reply-To: <7vy5e1sf6b.fsf@alter.siamese.dyndns.org>
From: "Junio C Hamano" <gitster@pobox.com>
Sent: Tuesday, March 05, 2013 9:35 PM
> Dale Worley <worley@c-66-31-108-177.hsd1.ma.comcast.net> writes:
>
>>> From: Junio C Hamano <gitster@pobox.com>
>>>
>>> I think this is to be expected for "git rebase", as it does not even
>>> look at merges. It is a way to find non-merge commits that haven't
>>> been applied yet, and apply them to the upstream to create a new
>>> linear history.
>>
>> I disagree. "git rebase" is not characterized as ...
>
> The intention has always been "I have these patches, some were
> applied upstream already, now what do I have left?".
Given that many folk appear to trip up with their rebase mindset, does
this suggest that a few tweaks to the manual may be in order to stop
such misunderstandings?
Perhaps:
git-rebase - Forward-port local commits, not in upstream,
to the updated upstream head
and to avoid "hidden" asides, add a few more paragraph breaks into the
description texts, and perhaps bring the "Note that any commits in HEAD
which introduce the same textual changes as a commit in HEAD..<upstream>
are omitted" sentence nearer the start.
That is, don't let folks get a too simplistic view of rebase, missing
its
hidden powers.
>
> You do realize that you are disagreeing with somebody who designed
> the original "git rebase" (before the --preserve-merges was added),
> do you?
However the broader userbase brings with it a better class of fool ;-)
^ permalink raw reply
* [PATCH v2 4/4] push: --follow-tags
From: Junio C Hamano @ 2013-03-05 22:47 UTC (permalink / raw)
To: git
In-Reply-To: <1362523639-30566-1-git-send-email-gitster@pobox.com>
The new option "--follow-tags" tells "git push" to push annotated
tags that are missing from the other side and that can be reached by
the history that is otherwise pushed out.
For example, if you are using the "simple", "current", or "upstream"
push, you would ordinarily push the history leading to the commit at
your current HEAD and nothing else. With this option, you would
also push all annotated tags that can be reached from that commit to
the other side.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
Documentation/git-push.txt | 8 +++-
builtin/push.c | 2 +
remote.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++
remote.h | 3 +-
t/t5516-fetch-push.sh | 73 ++++++++++++++++++++++++++++++++++
transport.c | 2 +
transport.h | 1 +
7 files changed, 186 insertions(+), 2 deletions(-)
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index 8b637d3..40377ba 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -9,7 +9,7 @@ git-push - Update remote refs along with associated objects
SYNOPSIS
--------
[verse]
-'git push' [--all | --mirror | --tags] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
+'git push' [--all | --mirror | --tags] [--follow-tags] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
[--repo=<repository>] [-f | --force] [--prune] [-v | --verbose] [-u | --set-upstream]
[<repository> [<refspec>...]]
@@ -111,6 +111,12 @@ no `push.default` configuration variable is set.
addition to refspecs explicitly listed on the command
line.
+--follow-tags::
+ Push all the refs that would be pushed without this option,
+ and also push annotated tags in `refs/tags` that are missing
+ from the remote but are pointing at committish that are
+ reachable from the refs being pushed.
+
--receive-pack=<git-receive-pack>::
--exec=<git-receive-pack>::
Path to the 'git-receive-pack' program on the remote
diff --git a/builtin/push.c b/builtin/push.c
index db9ba30..34a8271 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -399,6 +399,8 @@ int cmd_push(int argc, const char **argv, const char *prefix)
OPT_BOOL(0, "progress", &progress, N_("force progress reporting")),
OPT_BIT(0, "prune", &flags, N_("prune locally removed refs"),
TRANSPORT_PUSH_PRUNE),
+ OPT_BIT(0, "follow-tags", &flags, N_("push missing but relevant tags"),
+ TRANSPORT_PUSH_FOLLOW_TAGS),
OPT_END()
};
diff --git a/remote.c b/remote.c
index ca1f8f2..f035af3 100644
--- a/remote.c
+++ b/remote.c
@@ -1195,6 +1195,101 @@ static struct ref **tail_ref(struct ref **head)
return tail;
}
+struct tips {
+ struct commit **tip;
+ int nr, alloc;
+};
+
+static void add_to_tips(struct tips *tips, const unsigned char *sha1)
+{
+ struct commit *commit;
+
+ if (is_null_sha1(sha1))
+ return;
+ commit = lookup_commit_reference_gently(sha1, 1);
+ if (!commit || (commit->object.flags & TMP_MARK))
+ return;
+ commit->object.flags |= TMP_MARK;
+ ALLOC_GROW(tips->tip, tips->nr + 1, tips->alloc);
+ tips->tip[tips->nr++] = commit;
+}
+
+static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***dst_tail)
+{
+ struct string_list dst_tag = STRING_LIST_INIT_NODUP;
+ struct string_list src_tag = STRING_LIST_INIT_NODUP;
+ struct string_list_item *item;
+ struct ref *ref;
+ struct tips sent_tips;
+
+ /*
+ * Collect everything we know they would have at the end of
+ * this push, and collect all tags they have.
+ */
+ memset(&sent_tips, 0, sizeof(sent_tips));
+ for (ref = *dst; ref; ref = ref->next) {
+ if (ref->peer_ref &&
+ !is_null_sha1(ref->peer_ref->new_sha1))
+ add_to_tips(&sent_tips, ref->peer_ref->new_sha1);
+ else
+ add_to_tips(&sent_tips, ref->old_sha1);
+ if (!prefixcmp(ref->name, "refs/tags/"))
+ string_list_append(&dst_tag, ref->name);
+ }
+ clear_commit_marks_many(sent_tips.nr, sent_tips.tip, TMP_MARK);
+
+ sort_string_list(&dst_tag);
+
+ /* Collect tags they do not have. */
+ for (ref = src; ref; ref = ref->next) {
+ if (prefixcmp(ref->name, "refs/tags/"))
+ continue; /* not a tag */
+ if (string_list_has_string(&dst_tag, ref->name))
+ continue; /* they already have it */
+ if (sha1_object_info(ref->new_sha1, NULL) != OBJ_TAG)
+ continue; /* be conservative */
+ item = string_list_append(&src_tag, ref->name);
+ item->util = ref;
+ }
+ string_list_clear(&dst_tag, 0);
+
+ /*
+ * At this point, src_tag lists tags that are missing from
+ * dst, and sent_tips lists the tips we are pushing or those
+ * that we know they already have. An element in the src_tag
+ * that is an ancestor of any of the sent_tips needs to be
+ * sent to the other side.
+ */
+ if (sent_tips.nr) {
+ for_each_string_list_item(item, &src_tag) {
+ struct ref *ref = item->util;
+ struct ref *dst_ref;
+ struct commit *commit;
+
+ if (is_null_sha1(ref->new_sha1))
+ continue;
+ commit = lookup_commit_reference_gently(ref->new_sha1, 1);
+ if (!commit)
+ /* not pushing a commit, which is not an error */
+ continue;
+
+ /*
+ * Is this tag, which they do not have, reachable from
+ * any of the commits we are sending?
+ */
+ if (!in_merge_bases_many(commit, sent_tips.nr, sent_tips.tip))
+ continue;
+
+ /* Add it in */
+ dst_ref = make_linked_ref(ref->name, dst_tail);
+ hashcpy(dst_ref->new_sha1, ref->new_sha1);
+ dst_ref->peer_ref = copy_ref(ref);
+ }
+ }
+ string_list_clear(&src_tag, 0);
+ free(sent_tips.tip);
+}
+
/*
* Given the set of refs the local repository has, the set of refs the
* remote repository has, and the refspec used for push, determine
@@ -1257,6 +1352,10 @@ int match_push_refs(struct ref *src, struct ref **dst,
free_name:
free(dst_name);
}
+
+ if (flags & MATCH_REFS_FOLLOW_TAGS)
+ add_missing_tags(src, dst, &dst_tail);
+
if (send_prune) {
/* check for missing refs on the remote */
for (ref = *dst; ref; ref = ref->next) {
diff --git a/remote.h b/remote.h
index 251d8fd..a0731f1 100644
--- a/remote.h
+++ b/remote.h
@@ -148,7 +148,8 @@ enum match_refs_flags {
MATCH_REFS_NONE = 0,
MATCH_REFS_ALL = (1 << 0),
MATCH_REFS_MIRROR = (1 << 1),
- MATCH_REFS_PRUNE = (1 << 2)
+ MATCH_REFS_PRUNE = (1 << 2),
+ MATCH_REFS_FOLLOW_TAGS = (1 << 3)
};
/* Reporting of tracking info */
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index b5417cc..4ff2eb2 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -995,4 +995,77 @@ test_expect_success 'push --prune refspec' '
! check_push_result $the_first_commit tmp/foo tmp/bar
'
+test_expect_success 'fetch follows tags by default' '
+ mk_test heads/master &&
+ rm -fr src dst &&
+ git init src &&
+ (
+ cd src &&
+ git pull ../testrepo master &&
+ git tag -m "annotated" tag &&
+ git for-each-ref >tmp1 &&
+ (
+ cat tmp1
+ sed -n "s|refs/heads/master$|refs/remotes/origin/master|p" tmp1
+ ) |
+ sort -k 3 >../expect
+ ) &&
+ git init dst &&
+ (
+ cd dst &&
+ git remote add origin ../src &&
+ git config branch.master.remote origin &&
+ git config branch.master.merge refs/heads/master &&
+ git pull &&
+ git for-each-ref >../actual
+ ) &&
+ test_cmp expect actual
+'
+
+test_expect_success 'push does not follow tags by default' '
+ mk_test heads/master &&
+ rm -fr src dst &&
+ git init src &&
+ git init --bare dst &&
+ (
+ cd src &&
+ git pull ../testrepo master &&
+ git tag -m "annotated" tag &&
+ git checkout -b another &&
+ git commit --allow-empty -m "future commit" &&
+ git tag -m "future" future &&
+ git checkout master &&
+ git for-each-ref refs/heads/master >../expect &&
+ git push ../dst master
+ ) &&
+ (
+ cd dst &&
+ git for-each-ref >../actual
+ ) &&
+ test_cmp expect actual
+'
+
+test_expect_success 'push --follow-tag only pushes relevant tags' '
+ mk_test heads/master &&
+ rm -fr src dst &&
+ git init src &&
+ git init --bare dst &&
+ (
+ cd src &&
+ git pull ../testrepo master &&
+ git tag -m "annotated" tag &&
+ git checkout -b another &&
+ git commit --allow-empty -m "future commit" &&
+ git tag -m "future" future &&
+ git checkout master &&
+ git for-each-ref refs/heads/master refs/tags/tag >../expect
+ git push --follow-tag ../dst master
+ ) &&
+ (
+ cd dst &&
+ git for-each-ref >../actual
+ ) &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/transport.c b/transport.c
index b9306ef..9fe4aa3 100644
--- a/transport.c
+++ b/transport.c
@@ -1059,6 +1059,8 @@ int transport_push(struct transport *transport,
match_flags |= MATCH_REFS_MIRROR;
if (flags & TRANSPORT_PUSH_PRUNE)
match_flags |= MATCH_REFS_PRUNE;
+ if (flags & TRANSPORT_PUSH_FOLLOW_TAGS)
+ match_flags |= MATCH_REFS_FOLLOW_TAGS;
if (match_push_refs(local_refs, &remote_refs,
refspec_nr, refspec, match_flags)) {
diff --git a/transport.h b/transport.h
index 4a61c0c..8c493f7 100644
--- a/transport.h
+++ b/transport.h
@@ -104,6 +104,7 @@ struct transport {
#define TRANSPORT_RECURSE_SUBMODULES_CHECK 64
#define TRANSPORT_PUSH_PRUNE 128
#define TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND 256
+#define TRANSPORT_PUSH_FOLLOW_TAGS 1024
#define TRANSPORT_SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3)
#define TRANSPORT_SUMMARY(x) (int)(TRANSPORT_SUMMARY_WIDTH + strlen(x) - gettext_width(x)), (x)
--
1.8.2-rc2-194-g549a9ef
^ permalink raw reply related
* [PATCH v2 3/4] commit.c: use clear_commit_marks_many() in in_merge_bases_many()
From: Junio C Hamano @ 2013-03-05 22:47 UTC (permalink / raw)
To: git
In-Reply-To: <1362523639-30566-1-git-send-email-gitster@pobox.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
commit.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/commit.c b/commit.c
index d12e799..b4512ab 100644
--- a/commit.c
+++ b/commit.c
@@ -876,8 +876,7 @@ int in_merge_bases_many(struct commit *commit, int nr_reference, struct commit *
if (commit->object.flags & PARENT2)
ret = 1;
clear_commit_marks(commit, all_flags);
- for (i = 0; i < nr_reference; i++)
- clear_commit_marks(reference[i], all_flags);
+ clear_commit_marks_many(nr_reference, reference, all_flags);
free_commit_list(bases);
return ret;
}
--
1.8.2-rc2-194-g549a9ef
^ 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