Git development
 help / color / mirror / Atom feed
* [PATCH] git-p4: Fix error message crash in P4Sync.commit.
From: Tor Arvid Lund @ 2011-02-08 12:20 UTC (permalink / raw)
  To: git; +Cc: Tor Arvid Lund

There is an error message that crashes the script because of an invalid ref
to the non-existing "path" variable. It is almost never printed, which
would explain why nobody encountered this problem before... But anyway,
this oneliner fixes it.
---
 contrib/fast-import/git-p4 |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4
index ca3cea0..29b9e32 100755
--- a/contrib/fast-import/git-p4
+++ b/contrib/fast-import/git-p4
@@ -1086,7 +1086,7 @@ class P4Sync(Command):
             if [p for p in branchPrefixes if p4PathStartsWith(f['path'], p)]:
                 new_files.append (f)
             else:
-                sys.stderr.write("Ignoring file outside of prefix: %s\n" % path)
+                sys.stderr.write("Ignoring file outside of prefix: %s\n" % f['path'])
 
         self.gitStream.write("commit %s\n" % branch)
 #        gitStream.write("mark :%s\n" % details["change"])
-- 
1.7.3.1.68.g06779.dirty

^ permalink raw reply related

* [PATCH/RFC 0/7] Column output
From: Nguyễn Thái Ngọc Duy @ 2011-02-08 15:22 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

This series was made a year ago [1]. I'm quite happy with it so far
and also tired of maintaining off-tree. So here's another attempt to
clean it up and put it upstream.

In short, the series is very simple: give porcelain commands column
output, just like good old "ls". There could be a few more candidates,
I believe René Scharfe mentioned other files in "git status".

Another thing is how you want to customize this. Currently it supports
two modes: equal columns, and dense mode, specified with
--column=column or --column=dense. Obviously not very convenient.
There's core.column but I'm not sure how to specify modes there, and
if people like some more modes (fill rows before columns for example).

[1] http://mid.gmane.org/1267963785-473-1-git-send-email-pclouds@gmail.com

Nguyễn Thái Ngọc Duy (7):
  Move term_columns() to pager.c and save terminal width before pager
  Add column layout
  parseopt: OPT_COLUMN to set struct column_layout.mode
  add core.column
  help: reuse struct column_layout
  tag: support column output with --column
  branch: support column output with --column

 .gitignore                   |    1 +
 Documentation/config.txt     |    8 ++
 Documentation/git-branch.txt |    8 ++
 Documentation/git-tag.txt    |   11 ++-
 Makefile                     |    3 +
 builtin/branch.c             |   22 ++++-
 builtin/tag.c                |   19 ++++-
 cache.h                      |    2 +
 column.c                     |  195 ++++++++++++++++++++++++++++++++++++++++++
 column.h                     |   23 +++++
 config.c                     |   16 ++++
 environment.c                |    1 +
 help.c                       |   55 +++----------
 pager.c                      |   32 +++++++
 parse-options.h              |    2 +
 t/t9002-column.sh            |  108 +++++++++++++++++++++++
 test-column.c                |   59 +++++++++++++
 17 files changed, 514 insertions(+), 51 deletions(-)
 create mode 100644 column.c
 create mode 100644 column.h
 create mode 100755 t/t9002-column.sh
 create mode 100644 test-column.c

-- 
1.7.2.2

^ permalink raw reply

* [PATCH 1/7] Move term_columns() to pager.c and save terminal width before pager
From: Nguyễn Thái Ngọc Duy @ 2011-02-08 15:22 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <1297178541-31124-1-git-send-email-pclouds@gmail.com>

term_columns() checks for terminal width via ioctl(1). After
redirecting, stdin is no longer terminal to get terminal width.

Check terminal width and save it before redirect stdin in setup_pager()
and let term_columns() reuse the value.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 cache.h |    1 +
 help.c  |   22 ----------------------
 pager.c |   32 ++++++++++++++++++++++++++++++++
 3 files changed, 33 insertions(+), 22 deletions(-)

diff --git a/cache.h b/cache.h
index d83d68c..bcbd5f2 100644
--- a/cache.h
+++ b/cache.h
@@ -1045,6 +1045,7 @@ extern void setup_pager(void);
 extern const char *pager_program;
 extern int pager_in_use(void);
 extern int pager_use_color;
+extern int term_columns();
 
 extern const char *editor_program;
 extern const char *askpass_program;
diff --git a/help.c b/help.c
index 7654f1b..1344208 100644
--- a/help.c
+++ b/help.c
@@ -5,28 +5,6 @@
 #include "help.h"
 #include "common-cmds.h"
 
-/* most GUI terminals set COLUMNS (although some don't export it) */
-static int term_columns(void)
-{
-	char *col_string = getenv("COLUMNS");
-	int n_cols;
-
-	if (col_string && (n_cols = atoi(col_string)) > 0)
-		return n_cols;
-
-#ifdef TIOCGWINSZ
-	{
-		struct winsize ws;
-		if (!ioctl(1, TIOCGWINSZ, &ws)) {
-			if (ws.ws_col)
-				return ws.ws_col;
-		}
-	}
-#endif
-
-	return 80;
-}
-
 void add_cmdname(struct cmdnames *cmds, const char *name, int len)
 {
 	struct cmdname *ent = xmalloc(sizeof(*ent) + len + 1);
diff --git a/pager.c b/pager.c
index dac358f..ad447cf 100644
--- a/pager.c
+++ b/pager.c
@@ -12,6 +12,7 @@
  */
 
 static int spawned_pager;
+static int max_columns;
 
 #ifndef WIN32
 static void pager_preexec(void)
@@ -80,6 +81,15 @@ void setup_pager(void)
 
 	spawned_pager = 1; /* means we are emitting to terminal */
 
+#ifdef TIOCGWINSZ
+	{
+		struct winsize ws;
+		if (!ioctl(1, TIOCGWINSZ, &ws)) {
+			if (ws.ws_col)
+				max_columns = ws.ws_col;
+		}
+	}
+#endif
 	/* spawn the pager */
 	pager_argv[0] = pager;
 	pager_process.use_shell = 1;
@@ -116,3 +126,25 @@ int pager_in_use(void)
 	env = getenv("GIT_PAGER_IN_USE");
 	return env ? git_config_bool("GIT_PAGER_IN_USE", env) : 0;
 }
+
+int term_columns()
+{
+	char *col_string = getenv("COLUMNS");
+	int n_cols;
+
+	if (col_string && (n_cols = atoi(col_string)) > 0)
+		return n_cols;
+
+	else if (spawned_pager && max_columns)
+		return max_columns;
+#ifdef TIOCGWINSZ
+	else {
+		struct winsize ws;
+		if (!ioctl(1, TIOCGWINSZ, &ws)) {
+			if (ws.ws_col)
+				return ws.ws_col;
+		}
+	}
+#endif
+	return 80;
+}
-- 
1.7.2.2

^ permalink raw reply related

* [PATCH 2/7] Add column layout
From: Nguyễn Thái Ngọc Duy @ 2011-02-08 15:22 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <1297178541-31124-1-git-send-email-pclouds@gmail.com>

This mainly add display_columns() that will display a table of items,
filling columns before rows.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 .gitignore        |    1 +
 Makefile          |    3 +
 column.c          |  177 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 column.h          |   20 ++++++
 t/t9002-column.sh |  108 ++++++++++++++++++++++++++++++++
 test-column.c     |   59 ++++++++++++++++++
 6 files changed, 368 insertions(+), 0 deletions(-)
 create mode 100644 column.c
 create mode 100644 column.h
 create mode 100755 t/t9002-column.sh
 create mode 100644 test-column.c

diff --git a/.gitignore b/.gitignore
index 3dd6ef7..a1a1202 100644
--- a/.gitignore
+++ b/.gitignore
@@ -162,6 +162,7 @@
 /gitweb/gitweb.cgi
 /gitweb/static/gitweb.min.*
 /test-chmtime
+/test-column
 /test-ctype
 /test-date
 /test-delta
diff --git a/Makefile b/Makefile
index 775ee83..6d74956 100644
--- a/Makefile
+++ b/Makefile
@@ -417,6 +417,7 @@ PROGRAM_OBJS += http-backend.o
 PROGRAMS += $(patsubst %.o,git-%$X,$(PROGRAM_OBJS))
 
 TEST_PROGRAMS_NEED_X += test-chmtime
+TEST_PROGRAMS_NEED_X += test-column
 TEST_PROGRAMS_NEED_X += test-ctype
 TEST_PROGRAMS_NEED_X += test-date
 TEST_PROGRAMS_NEED_X += test-delta
@@ -498,6 +499,7 @@ LIB_H += builtin.h
 LIB_H += cache.h
 LIB_H += cache-tree.h
 LIB_H += color.h
+LIB_H += column.h
 LIB_H += commit.h
 LIB_H += compat/bswap.h
 LIB_H += compat/cygwin.h
@@ -575,6 +577,7 @@ LIB_OBJS += branch.o
 LIB_OBJS += bundle.o
 LIB_OBJS += cache-tree.o
 LIB_OBJS += color.o
+LIB_OBJS += column.o
 LIB_OBJS += combine-diff.o
 LIB_OBJS += commit.o
 LIB_OBJS += config.o
diff --git a/column.c b/column.c
new file mode 100644
index 0000000..4b92fa5
--- /dev/null
+++ b/column.c
@@ -0,0 +1,177 @@
+#include "cache.h"
+#include "column.h"
+#include "parse-options.h"
+
+static int item_length(const struct column_layout *c, const char *s)
+{
+	int a_len = 0;
+
+	if (!(c->mode & COL_ANSI))
+		return strlen(s);
+
+	while ((s = strstr(s, "\033[")) != NULL) {
+		int len = strspn(s+2, "0123456789;");
+		s += len+3; /* \033[<len><func char> */
+		a_len += len+3;
+	}
+	return a_len;
+}
+
+static void layout(const struct column_layout *c,
+		   int total_width, int padding,
+		   int *width,
+		   int *rows, int *cols)
+{
+	int i;
+
+	*width = 0;
+	/* Find maximum column width */
+	for (i = 0; i < c->items.nr; i++) {
+		const char *s = c->items.items[i].string;
+		int len = item_length(c, s);
+		if (*width < len)
+			*width = len;
+	}
+	*width += padding;
+
+	*cols = total_width / *width;
+	if (*cols == 0)
+		*cols = 1;
+	/* items.nr <= rows*cols -> rows >= items.nr/cols */
+	*rows = c->items.nr / *cols;
+	if (c->items.nr > *rows * *cols)
+		(*rows)++;
+}
+
+static int squeeze_columns(const struct column_layout *c,
+			   int *width, int padding,
+			   int rows, int cols)
+{
+	int x, y, i, len, item_len, spare = 0;
+	const char *s;
+
+	for (x = 0; x < cols; x++) {
+		for (y = len = 0; y < rows; y++) {
+			i = x * rows + y;
+			if (i >= c->items.nr)
+				break;
+			s = c->items.items[i].string;
+			item_len = item_length(c, s);
+			if (len < item_len)
+				len = item_len;
+		}
+		len += padding;
+		if (len < width[x]) {
+			spare += width[x] - len;
+			width[x] = len;
+		}
+	}
+	return spare;
+}
+
+static void relayout(const struct column_layout *c,
+		     int padding, int spare,
+		     int *initial_width, int **width,
+		     int *rows, int *cols)
+{
+	int new_rows, new_cols, new_initial_width;
+	int i, *new_width, new_spare, total_width;
+
+	/*
+	 * Assume all columns have same width, we would need
+	 * initial_width*cols. But then after squeezing, we have
+	 * "spare" more chars. Assume a new total_width with
+	 * additional chars, then re-squeeze to see if it fits
+	 * c->width.
+	 */
+	total_width = (*initial_width)*(*cols) + spare;
+	layout(c, total_width, padding,
+	       &new_initial_width, &new_rows, &new_cols);
+	new_width = xmalloc(sizeof(*new_width) * new_cols);
+	for (i = 0; i < new_cols; i++)
+		new_width[i] = new_initial_width;
+	new_spare = squeeze_columns(c, new_width, padding, new_rows, new_cols);
+
+	/* Does it fit? */
+	if (total_width - new_spare < c->width) {
+		free(*width);
+		*width = new_width;
+		*initial_width = new_initial_width;
+		*rows = new_rows;
+		*cols = new_cols;
+	}
+}
+
+static void display_columns_first(const struct column_layout *c,
+				  int padding, const char *indent)
+{
+	int x, y, i, cols, rows, initial_width, *width;
+	char *empty_cell;
+
+	layout(c, c->width, padding, &initial_width, &rows, &cols);
+	width = xmalloc(sizeof(*width) * cols);
+	for (i = 0; i < cols; i++)
+		width[i] = initial_width;
+
+	if (c->mode & COL_DENSE) {
+		int spare = squeeze_columns(c, width, padding, rows, cols);
+		/* is it worth relayout? */
+		if (spare >= initial_width/2)
+			relayout(c, padding, spare,
+				 &initial_width, &width, &rows, &cols);
+	}
+
+	empty_cell = xmalloc(initial_width + 1);
+	memset(empty_cell, ' ', initial_width);
+	empty_cell[initial_width] = '\0';
+	for (y = 0; y < rows; y++) {
+		for (x = 0; x < cols; x++) {
+			const char *s;
+			int len;
+
+			i = x * rows + y;
+			if (i >= c->items.nr)
+				break;
+			s = c->items.items[i].string;
+			len = item_length(c, s);
+			if (width[x] < initial_width)
+				len += initial_width - width[x];
+
+			printf("%s%s%s",
+			       x == 0 ? indent : "",
+			       c->items.items[i].string,
+			       /* If the next column at same row is
+				  out of range, end the line. Else pad
+				  some space.  */
+			       i + rows >= c->items.nr ? "\n" : empty_cell + len);
+		}
+	}
+}
+
+static void display_plain(const struct column_layout *c, const char *indent)
+{
+	int i;
+
+	for (i = 0; i < c->items.nr; i++)
+		printf("%s%s\n", indent, c->items.items[i].string);
+}
+
+void display_columns(const struct column_layout *c, int padding, const char *indent)
+{
+	int mode = c->mode & COL_MODE;
+	if (!indent)
+		indent = "";
+	if (c->width <= 1)
+		mode = COL_PLAIN;
+	switch (mode) {
+	case COL_PLAIN:
+		display_plain(c, indent);
+		break;
+
+	case COL_COLUMN_FIRST:
+		display_columns_first(c, padding, indent);
+		break;
+	default:
+		die("BUG: invalid mode %d", c->mode & COL_MODE);
+	}
+}
diff --git a/column.h b/column.h
new file mode 100644
index 0000000..34435b0
--- /dev/null
+++ b/column.h
@@ -0,0 +1,20 @@
+#ifndef COLUMN_H
+#define COLUMN_H
+
+#include "string-list.h"
+
+#define COL_MODE          0x000F
+#define COL_PLAIN         0 /* Single column */
+#define COL_COLUMN_FIRST  1 /* Fill columns before rows */
+#define COL_ANSI          (1 << 4) /* Remove ANSI from string length */
+#define COL_DENSE         (1 << 5) /* "Ragged-right" mode, relayout if enough space */
+
+struct column_layout {
+	int mode;
+	int width;
+	struct string_list items;
+};
+
+extern void display_columns(const struct column_layout *c, int padding, const char *indent);
+
+#endif
diff --git a/t/t9002-column.sh b/t/t9002-column.sh
new file mode 100755
index 0000000..1d030b0
--- /dev/null
+++ b/t/t9002-column.sh
@@ -0,0 +1,108 @@
+#!/bin/sh
+
+test_description='git column'
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	cat >lista <<\EOF
+one
+two
+three
+four
+five
+six
+seven
+eight
+nine
+ten
+eleven
+EOF
+'
+
+test_expect_success '80 columns' '
+	cat >expected <<\EOF &&
+one    two    three  four   five   six    seven  eight  nine   ten    eleven
+EOF
+	COLUMNS=80 test-column < lista > actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'COLUMNS = 1' '
+	cat >expected <<\EOF &&
+one
+two
+three
+four
+five
+six
+seven
+eight
+nine
+ten
+eleven
+EOF
+	COLUMNS=1 test-column < lista > actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'width = 1' '
+	test-column --width=1 < lista > actual &&
+	test_cmp expected actual
+'
+
+COLUMNS=20
+export COLUMNS
+
+test_expect_success '20 columns' '
+	cat >expected <<\EOF &&
+one    seven
+two    eight
+three  nine
+four   ten
+five   eleven
+six
+EOF
+	test-column < lista > actual &&
+	test_cmp expected actual
+'
+
+test_expect_success '20 columns, densed' '
+	cat >expected <<\EOF &&
+one   seven
+two   eight
+three nine
+four  ten
+five  eleven
+six
+EOF
+	test-column --mode=column,dense < lista > actual &&
+	test_cmp expected actual
+'
+
+test_expect_success '20 columns, padding 2' '
+	cat >expected <<\EOF &&
+one     seven
+two     eight
+three   nine
+four    ten
+five    eleven
+six
+EOF
+	test-column --padding 2 < lista > actual &&
+	test_cmp expected actual
+'
+
+test_expect_success '20 columns, left indented' '
+	cat >expected <<\EOF &&
+  one    seven
+  two    eight
+  three  nine
+  four   ten
+  five   eleven
+  six
+EOF
+	test-column --left=2 < lista > actual &&
+	test_cmp expected actual
+'
+
+test_done
diff --git a/test-column.c b/test-column.c
new file mode 100644
index 0000000..4f56cd8
--- /dev/null
+++ b/test-column.c
@@ -0,0 +1,59 @@
+#include "cache.h"
+#include "strbuf.h"
+#include "parse-options.h"
+#include "column.h"
+
+static const char * const builtin_column_usage[] = {
+	"git column [--mode=<mode>] [--width=<width>] [--left-space=<N>] [--right-space=<N>]",
+	NULL
+};
+
+int main(int argc, const char **argv)
+{
+	struct column_layout c;
+	const char *mode = NULL;
+	struct strbuf sb = STRBUF_INIT;
+	int left_space = 0, right_space = 0, padding = 1;
+	int term_width = term_columns();
+	struct option options[] = {
+		OPT_INTEGER(0, "width", &term_width, "Maximum width"),
+		OPT_INTEGER(0, "left", &left_space, "Padding space on left border"),
+		OPT_INTEGER(0, "right", &right_space, "Padding space on right border"),
+		OPT_INTEGER(0, "padding", &padding, "Padding space between columns"),
+		OPT_STRING(0, "mode", &mode, "mode", "Which layout mode to use"),
+		OPT_END()
+	};
+
+	argc = parse_options(argc, argv, "", options, builtin_column_usage, 0);
+
+	memset(&c, 0, sizeof(c));
+	c.width = term_width - right_space - left_space;
+	c.items.strdup_strings = 1;
+
+	while (mode && *mode) {
+		int len = strcspn(mode, ",");
+		if (len == 6 && !strncmp(mode, "column", len))
+			c.mode |= COL_COLUMN_FIRST;
+		else if (len == 5 && !strncmp(mode, "dense", len))
+			c.mode |= COL_DENSE;
+		else if (len == 4 && !strncmp(mode, "ansi", len))
+			c.mode |= COL_ANSI;
+		else
+			die("Unknown mode %s", mode);
+		mode += len;
+		while (*mode == ',')
+			mode++;
+	}
+	if (!c.mode)
+		c.mode = COL_COLUMN_FIRST;
+	if ((c.mode & COL_MODE) == 0)
+		die("Invalid mode '%s'", mode);
+
+	while (!strbuf_getline(&sb, stdin, '\n'))
+		string_list_append(&c.items, sb.buf);
+
+	strbuf_setlen(&sb, left_space);
+	memset(sb.buf, ' ', left_space);
+	display_columns(&c, padding, sb.buf);
+	return 0;
+}
-- 
1.7.2.2

^ permalink raw reply related

* [PATCH 3/7] parseopt: OPT_COLUMN to set struct column_layout.mode
From: Nguyễn Thái Ngọc Duy @ 2011-02-08 15:22 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <1297178541-31124-1-git-send-email-pclouds@gmail.com>


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 column.c        |   18 ++++++++++++++++++
 column.h        |    3 +++
 parse-options.h |    2 ++
 3 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/column.c b/column.c
index 4b92fa5..c4a90d5 100644
--- a/column.c
+++ b/column.c
@@ -175,3 +175,21 @@ void display_columns(const struct column_layout *c, int padding, const char *ind
 		die("BUG: invalid mode %d", c->mode & COL_MODE);
 	}
 }
+
+int parseopt_column_callback(const struct option *opt, const char *arg, int unset)
+{
+	struct column_layout *cp = opt->value;
+	if (unset) {
+		cp->mode = COL_PLAIN;
+		return 0;
+	}
+	if (!arg || !strcmp(arg, "column")) {
+		cp->mode |= COL_COLUMN_FIRST;
+		return 0;
+	}
+	if (!strcmp(arg, "dense")) {
+		cp->mode |= COL_DENSE;
+		return 0;
+	}
+	return error("unsupported style '%s'", arg);
+}
diff --git a/column.h b/column.h
index 34435b0..7f0ae74 100644
--- a/column.h
+++ b/column.h
@@ -17,4 +17,7 @@ struct column_layout {
 
 extern void display_columns(const struct column_layout *c, int padding, const char *indent);
 
+struct option;
+extern int parseopt_column_callback(const struct option *opt, const char *arg, int unset);
+
 #endif
diff --git a/parse-options.h b/parse-options.h
index 31ec5d2..2fed453 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -145,6 +145,8 @@ struct option {
 #define OPT_COLOR_FLAG(s, l, v, h) \
 	{ OPTION_CALLBACK, (s), (l), (v), "when", (h), PARSE_OPT_OPTARG, \
 		parse_opt_color_flag_cb, (intptr_t)"always" }
+#define OPT_COLUMN(s, l, v, h) \
+	{ OPTION_CALLBACK, (s), (l), (v), "style", (h), PARSE_OPT_OPTARG, parseopt_column_callback }
 
 
 /* parse_options() will filter out the processed options and leave the
-- 
1.7.2.2

^ permalink raw reply related

* [PATCH 5/7] help: reuse struct column_layout
From: Nguyễn Thái Ngọc Duy @ 2011-02-08 15:22 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <1297178541-31124-1-git-send-email-pclouds@gmail.com>


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 help.c |   33 +++++++++++----------------------
 1 files changed, 11 insertions(+), 22 deletions(-)

diff --git a/help.c b/help.c
index 1344208..dc06f63 100644
--- a/help.c
+++ b/help.c
@@ -4,6 +4,7 @@
 #include "levenshtein.h"
 #include "help.h"
 #include "common-cmds.h"
+#include "column.h"
 
 void add_cmdname(struct cmdnames *cmds, const char *name, int len)
 {
@@ -72,29 +73,17 @@ void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes)
 
 static void pretty_print_string_list(struct cmdnames *cmds, int longest)
 {
-	int cols = 1, rows;
-	int space = longest + 1; /* min 1 SP between words */
-	int max_cols = term_columns() - 1; /* don't print *on* the edge */
-	int i, j;
-
-	if (space < max_cols)
-		cols = max_cols / space;
-	rows = DIV_ROUND_UP(cmds->cnt, cols);
+	struct column_layout c;
+	int i;
 
-	for (i = 0; i < rows; i++) {
-		printf("  ");
+	memset(&c, 0, sizeof(c));
+	c.mode = COL_COLUMN_FIRST;
+	c.width = term_columns();
 
-		for (j = 0; j < cols; j++) {
-			int n = j * rows + i;
-			int size = space;
-			if (n >= cmds->cnt)
-				break;
-			if (j == cols-1 || n + rows >= cmds->cnt)
-				size = 1;
-			printf("%-*s", size, cmds->names[n]->name);
-		}
-		putchar('\n');
-	}
+	for (i = 0; i < cmds->cnt; i++)
+		string_list_append(&c.items, cmds->names[i]->name);
+	display_columns(&c, 2, "  ");
+	string_list_clear(&c.items, 0);
 }
 
 static int is_executable(const char *name)
-- 
1.7.2.2

^ permalink raw reply related

* [PATCH 4/7] add core.column
From: Nguyễn Thái Ngọc Duy @ 2011-02-08 15:22 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <1297178541-31124-1-git-send-email-pclouds@gmail.com>

This takes auto, never or always to enable column output for
porcelain commands.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Documentation/config.txt |    8 ++++++++
 cache.h                  |    1 +
 config.c                 |   16 ++++++++++++++++
 environment.c            |    1 +
 4 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index c5e1835..6d7151b 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -567,6 +567,14 @@ core.sparseCheckout::
 	Enable "sparse checkout" feature. See section "Sparse checkout" in
 	linkgit:git-read-tree[1] for more information.
 
+core.column::
+	Specify whether a command should output in columns. Only commands
+	that support `--column` will be affected by this. This variable can
+	take either `never` (do not output in columns), `auto` (output in
+	columns if the output is to a terminal) or `always` (always output in
+	columns). Setting `--column` or `--no-column` will override this
+	variable. This option defaults to never.
+
 add.ignore-errors::
 add.ignoreErrors::
 	Tells 'git add' to continue adding files when some files cannot be
diff --git a/cache.h b/cache.h
index bcbd5f2..1fa7656 100644
--- a/cache.h
+++ b/cache.h
@@ -559,6 +559,7 @@ extern int read_replace_refs;
 extern int fsync_object_files;
 extern int core_preload_index;
 extern int core_apply_sparse_checkout;
+extern int core_column;
 
 enum safe_crlf {
 	SAFE_CRLF_FALSE = 0,
diff --git a/config.c b/config.c
index 625e051..071899f 100644
--- a/config.c
+++ b/config.c
@@ -9,6 +9,8 @@
 #include "exec_cmd.h"
 #include "strbuf.h"
 #include "quote.h"
+#include "color.h"
+#include "column.h"
 
 #define MAXNAME (256)
 
@@ -660,6 +662,20 @@ static int git_default_core_config(const char *var, const char *value)
 		return 0;
 	}
 
+	if (!strcmp(var, "core.column")) {
+		switch (git_config_colorbool(var, value, -1)) {
+		case 0:
+			core_column = COL_PLAIN;
+			break;
+		case 1:
+			core_column = COL_COLUMN_FIRST;
+			break;
+		case -1:
+			return -1;
+		}
+		return 0;
+	}
+
 	/* Add other config variables here and to Documentation/config.txt. */
 	return 0;
 }
diff --git a/environment.c b/environment.c
index 9564475..b420ea2 100644
--- a/environment.c
+++ b/environment.c
@@ -56,6 +56,7 @@ char *notes_ref_name;
 int grafts_replace_parents = 1;
 int core_apply_sparse_checkout;
 struct startup_info *startup_info;
+int core_column;
 
 /* Parallel index stat data preload? */
 int core_preload_index = 0;
-- 
1.7.2.2

^ permalink raw reply related

* [PATCH 6/7] tag: support column output with --column
From: Nguyễn Thái Ngọc Duy @ 2011-02-08 15:22 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <1297178541-31124-1-git-send-email-pclouds@gmail.com>


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Documentation/git-tag.txt |   11 ++++++++++-
 builtin/tag.c             |   19 ++++++++++++++++---
 2 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt
index 8b169e3..7a3ae28 100644
--- a/Documentation/git-tag.txt
+++ b/Documentation/git-tag.txt
@@ -12,7 +12,8 @@ SYNOPSIS
 'git tag' [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>]
 	<tagname> [<commit> | <object>]
 'git tag' -d <tagname>...
-'git tag' [-n[<num>]] -l [--contains <commit>] [<pattern>]
+'git tag' [-n[<num>]] -l [--[no-]column[=<options>[,<option>]*]]
+	[--contains <commit>] [<pattern>]
 'git tag' -v <tagname>...
 
 DESCRIPTION
@@ -71,6 +72,14 @@ OPTIONS
 	List tags with names that match the given pattern (or all if no pattern is given).
 	Typing "git tag" without arguments, also lists all tags.
 
+--column::
+	Show tags in columns. This option is only applicable if `git tag` is
+	used to list tags without annotation lines.
+
+--no-column::
+	Show tags in a single list. This option is used to override core.columns
+	if set. This option is only applicable if `git tag` is used to list tags.
+
 --contains <commit>::
 	Only list tags which contain the specified commit.
 
diff --git a/builtin/tag.c b/builtin/tag.c
index aa1f87d..b74b8bf 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -12,6 +12,7 @@
 #include "tag.h"
 #include "run-command.h"
 #include "parse-options.h"
+#include "column.h"
 
 static const char * const git_tag_usage[] = {
 	"git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]",
@@ -22,6 +23,7 @@ static const char * const git_tag_usage[] = {
 };
 
 static char signingkey[1000];
+static struct column_layout layout;
 
 struct tag_filter {
 	const char *pattern;
@@ -52,7 +54,7 @@ static int show_reference(const char *refname, const unsigned char *sha1,
 		}
 
 		if (!filter->lines) {
-			printf("%s\n", refname);
+			string_list_append(&layout.items, refname);
 			return 0;
 		}
 		printf("%-15s ", refname);
@@ -383,6 +385,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 		OPT_STRING('u', NULL, &keyid, "key-id",
 					"use another key to sign the tag"),
 		OPT__FORCE(&force, "replace the tag if exists"),
+		OPT_COLUMN(0, "column", &layout, "show tag list in columns" ),
 
 		OPT_GROUP("Tag listing options"),
 		{
@@ -395,6 +398,9 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 	};
 
 	git_config(git_tag_config, NULL);
+	layout.mode = core_column;
+	layout.width = term_columns();
+	layout.items.strdup_strings = 1;
 
 	argc = parse_options(argc, argv, prefix, options, git_tag_usage, 0);
 
@@ -413,9 +419,16 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 
 	if (list + delete + verify > 1)
 		usage_with_options(git_tag_usage, options);
-	if (list)
-		return list_tags(argv[0], lines == -1 ? 0 : lines,
+	if (list) {
+		int ret;
+
+		if (lines != -1)
+			layout.mode = COL_PLAIN;
+		ret =  list_tags(argv[0], lines == -1 ? 0 : lines,
 				 with_commit);
+		display_columns(&layout, 2, "");
+		return ret;
+	}
 	if (lines != -1)
 		die("-n option is only allowed with -l.");
 	if (with_commit)
-- 
1.7.2.2

^ permalink raw reply related

* [PATCH 7/7] branch: support column output with --column
From: Nguyễn Thái Ngọc Duy @ 2011-02-08 15:22 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <1297178541-31124-1-git-send-email-pclouds@gmail.com>


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Documentation/git-branch.txt |    8 ++++++++
 builtin/branch.c             |   22 +++++++++++++++++++---
 2 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index 9106d38..3ec997a 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -9,6 +9,7 @@ SYNOPSIS
 --------
 [verse]
 'git branch' [--color[=<when>] | --no-color] [-r | -a]
+	[--[no-]column[=<options>[,<option>]*]]
 	[-v [--abbrev=<length> | --no-abbrev]]
 	[(--merged | --no-merged | --contains) [<commit>]]
 'git branch' [--set-upstream | --track | --no-track] [-l] [-f] <branchname> [<start-point>]
@@ -99,6 +100,13 @@ OPTIONS
 	default to color output.
 	Same as `--color=never`.
 
+--column::
+	Show branches in columns. This option is ignored in verbose mode.
+
+--no-column::
+	Show branches in a single list. This option is used to override
+	core.columns if set.
+
 -r::
 	List or delete (if used with -d) the remote-tracking branches.
 
diff --git a/builtin/branch.c b/builtin/branch.c
index 9e546e4..803fa5f 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -15,6 +15,7 @@
 #include "branch.h"
 #include "diff.h"
 #include "revision.h"
+#include "column.h"
 
 static const char * const builtin_branch_usage[] = {
 	"git branch [options] [-r | -a] [--merged | --no-merged]",
@@ -53,6 +54,8 @@ static enum merge_filter {
 } merge_filter;
 static unsigned char merge_filter_ref[20];
 
+static struct column_layout layout;
+
 static int parse_branch_color_slot(const char *var, int ofs)
 {
 	if (!strcasecmp(var+ofs, "plain"))
@@ -451,7 +454,7 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
 		strbuf_release(&stat);
 		strbuf_release(&subject);
 	}
-	printf("%s\n", out.buf);
+	string_list_append(&layout.items, out.buf);
 	strbuf_release(&name);
 	strbuf_release(&out);
 }
@@ -660,6 +663,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG,
 			opt_parse_merge_filter, (intptr_t) "HEAD",
 		},
+		OPT_COLUMN(0, "column", &layout, "list branches in columns" ),
 		OPT_END(),
 	};
 
@@ -686,6 +690,11 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 	}
 	hashcpy(merge_filter_ref, head_sha1);
 
+	memset(&layout, 0, sizeof(layout));
+	layout.mode = core_column;
+	layout.width = term_columns();
+	layout.items.strdup_strings = 1;
+
 	argc = parse_options(argc, argv, prefix, options, builtin_branch_usage,
 			     0);
 	if (!!delete + !!rename + !!force_create > 1)
@@ -693,8 +702,15 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 
 	if (delete)
 		return delete_branches(argc, argv, delete > 1, kinds);
-	else if (argc == 0)
-		return print_ref_list(kinds, detached, verbose, abbrev, with_commit);
+	else if (argc == 0) {
+		int ret;
+		if (verbose)
+			layout.mode = COL_PLAIN;
+
+		ret = print_ref_list(kinds, detached, verbose, abbrev, with_commit);
+		display_columns(&layout, 2, "");
+		return ret;
+	}
 	else if (rename && (argc == 1))
 		rename_branch(head, argv[0], rename > 1);
 	else if (rename && (argc == 2))
-- 
1.7.2.2

^ permalink raw reply related

* Supporting Kerberos auth over HTTP (mod_auth_kerb)
From: Nick @ 2011-02-08 17:07 UTC (permalink / raw)
  To: git

Has anyone gotten negotiable authentication to work with git over http
using mod_auth_kerb on the server end?  I am unable to get a git
client to function correctly in this scenario.  I am defining
"correctly" as the following:

When a valid kerberos ticket is available, use that without prompting
for credentials.  If for some reason that fails, prompt for
credentials and try again using HTTP basic auth.

If no valid kerberos ticket is available, prompt for credentials and
try using HTTP basic auth.



So far the behavior I have been able to reproduce:

When 'KrbMethodNegotiate off' is set on the server, the git client
will always prompt for username and password and use them.  This is
very intuitive from the user perspective, but does not take advantage
of the kerberos ticket for single sign-on.

When 'KrbMethodNegotiate on' is set on the server, the git client will
always prompt for username and password, but ignore them.  If a valid
kerberos ticket is available, the command will complete after any
arbitrary text is entered into the username and password prompts.  If
a valid kerberos ticket is not available, the command will fail even
if the correct username and password is entered.

Using some combinations of various git and curl versions and compile
options will not even get that far, and respond immediately with a
401.


I have tried several different versions of git, including the latest
1.7.4.  I have tried several different versions of curl, including the
latest 7.12.3.  I have tried several different curl compile-time
configuration options, including --with-spenego (using fbopenssl) and
--with-gssapi.

^ permalink raw reply

* Re: [PATCH] rebase: use @{upstream} if no upstream specified
From: Sverre Rabbelier @ 2011-02-08 17:46 UTC (permalink / raw)
  To: Martin von Zweigbergk; +Cc: git, Junio C Hamano, Yann Dirson
In-Reply-To: <1297125475-19151-1-git-send-email-martin.von.zweigbergk@gmail.com>

Heya,

On Tue, Feb 8, 2011 at 01:37, Martin von Zweigbergk
<martin.von.zweigbergk@gmail.com> wrote:
> Defaulting to @{upstream} will make it possible to run e.g. 'git
> rebase -i' without arguments, which is probably a quite common use
> case.

I particularly like that you explain to the user clearly what they
have to do to make this work (e.g., configure the upstream). Nice.

-- 
Cheers,

Sverre Rabbelier

^ permalink raw reply

* Re: What's cooking in git.git (Jan 2011, #06; Sun, 30)
From: Sverre Rabbelier @ 2011-02-08 17:48 UTC (permalink / raw)
  To: Junio C Hamano, Ævar Arnfjörð Bjarmason; +Cc: git
In-Reply-To: <AANLkTik4jZWLt6T-SwMgK94FJ77ujyUC4-oFD46-eqN=@mail.gmail.com>

Heya,

On Mon, Jan 31, 2011 at 16:08, Sverre Rabbelier <srabbelier@gmail.com> wrote:
> On Tue, Dec 14, 2010 at 03:20, Junio C Hamano <gitster@pobox.com> wrote:
>> Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
>>> On Mon, Dec 13, 2010 at 09:34, Junio C Hamano <gitster@pobox.com> wrote:
>>>
>>>> Needs a bit more minor work to get the basic code structure right.
>>>
>>> And I'm still not sure (see earlier replies to "What's Cooking" posts)
>>> what needs to be done to make it better.
>>
>> One open question was why you do not want to move 'LIB_OBJS += gettext.o'
>> away from the LIB_OBJS section down to the configuration evaluation
>> section, i.e., why gettext.o would be different from block-sha1/sha1.o.
>
> Ævar, you didn't respond to that message. Junio, do I understand
> correctly that if this problem is addressed the topic is ready to be
> merged to next?

It's been a week, no response from either Junio or Ævar ? :(

-- 
Cheers,

Sverre Rabbelier

^ permalink raw reply

* Re: [PATCH] rebase: use @{upstream} if no upstream specified
From: Martin von Zweigbergk @ 2011-02-08 18:23 UTC (permalink / raw)
  To: Sverre Rabbelier; +Cc: Martin von Zweigbergk, git, Junio C Hamano, Yann Dirson
In-Reply-To: <AANLkTi=Uqkzv+ucBzww6R1V+0ujmfH-dED8XJhyRvWQF@mail.gmail.com>

On Tue, 8 Feb 2011, Sverre Rabbelier wrote:

> Heya,
> 
> On Tue, Feb 8, 2011 at 01:37, Martin von Zweigbergk
> <martin.von.zweigbergk@gmail.com> wrote:
> > Defaulting to @{upstream} will make it possible to run e.g. 'git
> > rebase -i' without arguments, which is probably a quite common use
> > case.
> 
> I particularly like that you explain to the user clearly what they
> have to do to make this work (e.g., configure the upstream). Nice.

Thanks, but that was stolen from git-pull.sh ;-). Federico Mena
Quintero added it there in 8fc293c (Make git-pull complain and give
advice when there is nothing to merge with, 2007-10-02).

/Martin

^ permalink raw reply

* Re: [PATCH] rebase: use @{upstream} if no upstream specified
From: Sverre Rabbelier @ 2011-02-08 18:27 UTC (permalink / raw)
  To: Martin von Zweigbergk; +Cc: git, Junio C Hamano, Yann Dirson
In-Reply-To: <alpine.DEB.2.00.1102081320350.4475@debian>

Heya,

On Tue, Feb 8, 2011 at 19:23, Martin von Zweigbergk
<martin.von.zweigbergk@gmail.com> wrote:
> Thanks, but that was stolen from git-pull.sh ;-). Federico Mena
> Quintero added it there in 8fc293c (Make git-pull complain and give
> advice when there is nothing to merge with, 2007-10-02).

Credit where credit is due :), nonetheless, glad to see it here as well.

-- 
Cheers,

Sverre Rabbelier

^ permalink raw reply

* Re: [1.8.0] Provide proper remote ref namespaces
From: Enrico Weigelt @ 2011-02-08 19:11 UTC (permalink / raw)
  To: git
In-Reply-To: <201102080915.27484.johan@herland.net>

* Johan Herland <johan@herland.net> wrote:

> Ah, yes, I should have been more specific:
> 
>     remote.origin.fetch = ~refs/tags/*:refs/tags/*
> 
> In my proposal, I suggest using a "~" prefix to signal auto-following 
> behavior. This is needed in order to be able to explicitly specify the 
> current fetch behavior in the configuration.

Under the hood, this line could be automatically "added" (internally)
unless some "fetch.autotag = false" is given.


cu
-- 
----------------------------------------------------------------------
 Enrico Weigelt, metux IT service -- http://www.metux.de/

 phone:  +49 36207 519931  email: weigelt@metux.de
 mobile: +49 151 27565287  icq:   210169427         skype: nekrad666
----------------------------------------------------------------------
 Embedded-Linux / Portierung / Opensource-QM / Verteilte Systeme
----------------------------------------------------------------------

^ permalink raw reply

* Re: What's cooking in git.git (Jan 2011, #06; Sun, 30)
From: Junio C Hamano @ 2011-02-08 19:27 UTC (permalink / raw)
  To: Sverre Rabbelier; +Cc: Ævar Arnfjörð Bjarmason, git
In-Reply-To: <AANLkTikyHANL3y8VZ3LWu7bXkJwEHiiDLJ5NDZaA7z=b@mail.gmail.com>

Sverre Rabbelier <srabbelier@gmail.com> writes:

>> Ævar, you didn't respond to that message. Junio, do I understand
>> correctly that if this problem is addressed the topic is ready to be
>> merged to next?

Necessary? yes. Sufficient? I dunno, but it is a good start, I think.

^ permalink raw reply

* [PATCH v2] Add support for merging from upstream by default.
From: Jared Hance @ 2011-02-08 20:48 UTC (permalink / raw)
  To: git; +Cc: Jared Hance

Adds the option merge.defaultupstream to add support for merging from the
upstream branch by default. The upstream branch is found using
branch.[name].merge.

Also add helper functions `per_branch_config` and `setup_merge_commit` to
reduce reduncancy and impove clarity.

Signed-off-by: Jared Hance <jaredhance@gmail.com>
---
 Documentation/config.txt |    5 +++
 builtin/merge.c          |   81 +++++++++++++++++++++++++++++++++-------------
 2 files changed, 63 insertions(+), 23 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index c5e1835..25c8292 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -1389,6 +1389,11 @@ man.<tool>.path::
 
 include::merge-config.txt[]
 
+merge.defaultUpstream::
+	If merge is called without any ref arguments, merge from the branch
+	specified in branch.<current branch>.merge, which is considered to be
+	the upstream branch for the current branch.
+
 mergetool.<tool>.path::
 	Override the path for the given tool.  This is useful in case
 	your tool is not in the PATH.
diff --git a/builtin/merge.c b/builtin/merge.c
index 42fff38..2b4fd4f 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -37,7 +37,7 @@ struct strategy {
 };
 
 static const char * const builtin_merge_usage[] = {
-	"git merge [options] <remote>...",
+	"git merge [options] [<remote>...]",
 	"git merge [options] <msg> HEAD <remote>",
 	NULL
 };
@@ -58,6 +58,8 @@ static int option_renormalize;
 static int verbosity;
 static int allow_rerere_auto;
 static int abort_current_merge;
+static int default_upstream;
+static const char *upstream_branch;
 
 static struct strategy all_strategy[] = {
 	{ "recursive",  DEFAULT_TWOHEAD | NO_TRIVIAL },
@@ -498,11 +500,15 @@ cleanup:
 	strbuf_release(&bname);
 }
 
-static int git_merge_config(const char *k, const char *v, void *cb)
+static int per_branch_config(const char *k, const char *v, void *cb)
 {
-	if (branch && !prefixcmp(k, "branch.") &&
-		!prefixcmp(k + 7, branch) &&
-		!strcmp(k + 7 + strlen(branch), ".mergeoptions")) {
+	const char *variable;
+	if(!branch || prefixcmp(k, "branch.")
+	   || prefixcmp(k + 7, branch))
+		return 1; /* ignore me */
+
+	variable = k + 7 + strlen(branch);
+	if(!strcmp(variable, ".mergeoptions")) {
 		const char **argv;
 		int argc;
 		char *buf;
@@ -518,9 +524,26 @@ static int git_merge_config(const char *k, const char *v, void *cb)
 		parse_options(argc, argv, NULL, builtin_merge_options,
 			      builtin_merge_usage, 0);
 		free(buf);
+
+		return 0;
 	}
+	else if(strcmp(variable, ".merge")) {
+		return git_config_string(&upstream_branch, k, v);
+	}
+
+	return 1; /* not what I handle */
+}
 
-	if (!strcmp(k, "merge.diffstat") || !strcmp(k, "merge.stat"))
+static int git_merge_config(const char *k, const char *v, void *cb)
+{
+	int status = per_branch_config(k, v, cb);
+
+	if (status <= 0)
+		return status;
+
+	if (!strcmp(k, "merge.defaultupstream"))
+		default_upstream = git_config_bool(k, v);
+	else if (!strcmp(k, "merge.diffstat") || !strcmp(k, "merge.stat"))
 		show_diffstat = git_config_bool(k, v);
 	else if (!strcmp(k, "pull.twohead"))
 		return git_config_string(&pull_twohead, k, v);
@@ -911,6 +934,24 @@ static int evaluate_result(void)
 	return cnt;
 }
 
+static void setup_merge_commit(struct strbuf *buf,
+	struct commit_list ***remotes, const char *s)
+{
+	struct object *o;
+	struct commit *commit;
+
+	o = peel_to_type(s, 0, NULL, OBJ_COMMIT);
+	if (!o)
+		die("%s - not something we can merge", s);
+	commit = lookup_commit(o->sha1);
+	commit->util = (void *)s;
+	*remotes = &commit_list_insert(commit, *remotes)->next;
+
+	strbuf_addf(buf, "GITHEAD_%s", sha1_to_hex(o->sha1));
+	setenv(buf->buf, s, 1);
+	strbuf_reset(buf);
+}
+
 int cmd_merge(int argc, const char **argv, const char *prefix)
 {
 	unsigned char result_tree[20];
@@ -983,9 +1024,15 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 	if (!allow_fast_forward && fast_forward_only)
 		die("You cannot combine --no-ff with --ff-only.");
 
-	if (!argc)
-		usage_with_options(builtin_merge_usage,
-			builtin_merge_options);
+	if (!argc) {
+		if(default_upstream && upstream_branch) {
+			setup_merge_commit(&buf, &remotes, upstream_branch);
+		}
+		else {
+			usage_with_options(builtin_merge_usage,
+					builtin_merge_options);
+		}
+	}
 
 	/*
 	 * This could be traditional "merge <msg> HEAD <commit>..."  and
@@ -1048,7 +1095,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 		}
 	}
 
-	if (head_invalid || !argc)
+	if (head_invalid || (!argc && !(default_upstream && upstream_branch)))
 		usage_with_options(builtin_merge_usage,
 			builtin_merge_options);
 
@@ -1059,19 +1106,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 	strbuf_reset(&buf);
 
 	for (i = 0; i < argc; i++) {
-		struct object *o;
-		struct commit *commit;
-
-		o = peel_to_type(argv[i], 0, NULL, OBJ_COMMIT);
-		if (!o)
-			die("%s - not something we can merge", argv[i]);
-		commit = lookup_commit(o->sha1);
-		commit->util = (void *)argv[i];
-		remotes = &commit_list_insert(commit, remotes)->next;
-
-		strbuf_addf(&buf, "GITHEAD_%s", sha1_to_hex(o->sha1));
-		setenv(buf.buf, argv[i], 1);
-		strbuf_reset(&buf);
+		setup_merge_commit(&buf, &remotes, argv[i]);
 	}
 
 	if (!use_strategies) {
-- 
1.7.4

^ permalink raw reply related

* Re: [PATCH v2] Add support for merging from upstream by default.
From: Jay Soffian @ 2011-02-08 21:38 UTC (permalink / raw)
  To: Jared Hance; +Cc: git, Jeff King
In-Reply-To: <1297198129-3403-1-git-send-email-jaredhance@gmail.com>

On Tue, Feb 8, 2011 at 3:48 PM, Jared Hance <jaredhance@gmail.com> wrote:
>
> Adds the option merge.defaultupstream to add support for merging from the

Nit: I agree with Jeff[1] that this should be called merge.defaultToUpstream

[1] http://article.gmane.org/gmane.comp.version-control.git/165745

j.

^ permalink raw reply

* Re: [PATCH] rebase: use @{upstream} if no upstream specified
From: Jonathan Nieder @ 2011-02-08 22:05 UTC (permalink / raw)
  To: Martin von Zweigbergk; +Cc: Sverre Rabbelier, git, Junio C Hamano, Yann Dirson
In-Reply-To: <alpine.DEB.2.00.1102081320350.4475@debian>

Martin von Zweigbergk wrote:
> On Tue, 8 Feb 2011, Sverre Rabbelier wrote:

>> I particularly like that you explain to the user clearly what they
>> have to do to make this work (e.g., configure the upstream). Nice.
>
> Thanks, but that was stolen from git-pull.sh ;-)

Doesn't that suggest it might belong in some common git-upstream--lib.sh
(or git-sh-setup.sh)?

^ permalink raw reply

* Re: [PATCH v2] Add support for merging from upstream by default.
From: Jonathan Nieder @ 2011-02-08 22:33 UTC (permalink / raw)
  To: Jared Hance
  Cc: git, Martin von Zweigbergk, Andreas Schwab, Bert Wesarg,
	Jeff King, Felipe Contreras
In-Reply-To: <1297198129-3403-1-git-send-email-jaredhance@gmail.com>

Jared Hance wrote:

> Adds the option merge.defaultupstream to add support for merging from the
> upstream branch by default.

Could you give an example of breakage this configurability is designed
to prevent?

Not that it is a bad idea to be careful anyway, mind you --- just
looking for a clear answer for when people ask "and why would I ever
want to set merge.defaultToUpstream to false?"

> reduce reduncancy and impove clarity.

redundancy, improve :)

> --- a/Documentation/config.txt
> +++ b/Documentation/config.txt
> @@ -1389,6 +1389,11 @@ man.<tool>.path::
>  
>  include::merge-config.txt[]
>  
> +merge.defaultUpstream::
> +	If merge is called without any ref arguments, merge from the branch
> +	specified in branch.<current branch>.merge, which is considered to be
> +	the upstream branch for the current branch.

I'd prefer to say "merge from the branch configured with --track or
--set-upstream" (but that's just me).

> +++ b/builtin/merge.c
> @@ -37,7 +37,7 @@ struct strategy {
>  };
>  
>  static const char * const builtin_merge_usage[] = {
> -	"git merge [options] <remote>...",
> +	"git merge [options] [<remote>...]",
>  	"git merge [options] <msg> HEAD <remote>",
>  	NULL

Side note: these should probably say "<commit>" or "<branch>" rather
than "<remote>".  I'm guessing the usage string comes from the days
before the separate-remotes ref layout...

> @@ -58,6 +58,8 @@ static int option_renormalize;
[...]
> -static int git_merge_config(const char *k, const char *v, void *cb)
> +static int per_branch_config(const char *k, const char *v, void *cb)
>  {
> -	if (branch && !prefixcmp(k, "branch.") &&
> -		!prefixcmp(k + 7, branch) &&
> -		!strcmp(k + 7 + strlen(branch), ".mergeoptions")) {
> +	const char *variable;
> +	if(!branch || prefixcmp(k, "branch.")
> +	   || prefixcmp(k + 7, branch))
> +		return 1; /* ignore me */

Style: missing space after "if" keyword.

Clarity: we are not supposed to _ignore_ the non-branch.*
configuration, just leave it for other functions to handle, no?
Maybe the comment should say "let others handle it" or something?

> +
> +	variable = k + 7 + strlen(branch);

'7' can be written in a more self-explanatory way as 'strlen("branch.")'
and the optimizer will take care of translating it to 7.  Don't worry
about it if that makes the diff or code harder to read, though; I'm
just mentioning the trick for future reference.

> +	if(!strcmp(variable, ".mergeoptions")) {

Style: missing space after "if" keyword.

> @@ -518,9 +524,26 @@ static int git_merge_config(const char *k, const char *v, void *cb)
>  		parse_options(argc, argv, NULL, builtin_merge_options,
>  			      builtin_merge_usage, 0);
>  		free(buf);
> +
> +		return 0;

I'd group the cleanup with the return.

	parse_options(...);

	free(buf);
	return 0;

>  	}
> +	else if(strcmp(variable, ".merge")) {

Style: missing space after "if".  Uncuddled brace.

[...]
> @@ -911,6 +934,24 @@ static int evaluate_result(void)
>  	return cnt;
>  }
>  
> +static void setup_merge_commit(struct strbuf *buf,
> +	struct commit_list ***remotes, const char *s)
> +{
> +	struct object *o;
> +	struct commit *commit;
> +
> +	o = peel_to_type(s, 0, NULL, OBJ_COMMIT);
> +	if (!o)
> +		die("%s - not something we can merge", s);
> +	commit = lookup_commit(o->sha1);
> +	commit->util = (void *)s;
> +	*remotes = &commit_list_insert(commit, *remotes)->next;
> +
> +	strbuf_addf(buf, "GITHEAD_%s", sha1_to_hex(o->sha1));
> +	setenv(buf->buf, s, 1);
> +	strbuf_reset(buf);
> +}

Would be easier to review if this code movement were in a separate
patch (separating cleanup from semantic changes).

> @@ -983,9 +1024,15 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
>  	if (!allow_fast_forward && fast_forward_only)
>  		die("You cannot combine --no-ff with --ff-only.");
>  
> -	if (!argc)
> -		usage_with_options(builtin_merge_usage,
> -			builtin_merge_options);
> +	if (!argc) {
> +		if(default_upstream && upstream_branch) {

Style: missing space after "if".  Unnecessary braces.  To avoid
keeping the reader in suspense, it's usually best to handle the
(simple) error case first, like so:

		if (!default_upstream || !upstream_branch)
			usage_with_options(...);
		setup_merge_commit(...);

[...]
> @@ -1048,7 +1095,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
>  		}
>  	}
>  
> -	if (head_invalid || !argc)
> +	if (head_invalid || (!argc && !(default_upstream && upstream_branch)))

Might be clearer to split the line?

	if (head_invalid
	    || (!argc && (!default_upstream || !upstream_branch)))
		usage_with_options(...);
    
Even better would be to use descriptive messages, like so:

 if (head_invalid)
	usage_msg_opt("cannot use old-style invocation from an unborn branch",
		...);
 if (!argc && ...)
	usage_msg_opt("no commit to merge specified", ...);

Thanks for making this happen. :)
Jonathan

^ permalink raw reply

* Re: [PATCH/RFC 0/7] Column output
From: Jeff King @ 2011-02-08 22:47 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: git
In-Reply-To: <1297178541-31124-1-git-send-email-pclouds@gmail.com>

On Tue, Feb 08, 2011 at 10:22:14PM +0700, Nguyễn Thái Ngọc Duy wrote:

> In short, the series is very simple: give porcelain commands column
> output, just like good old "ls". There could be a few more candidates,
> I believe René Scharfe mentioned other files in "git status".

I don't really care for column output myself, so maybe you have a good
reason why my idea won't work. But why not use the BSD column program?
I.e.:

  git config pager.tag column
  git config pager.branch column

True it will use "column" no matter whether the specific branch or tag
operation produces a lot of output or not, but in general that should be
OK. Most "action" commands like "tag -d" or "branch new old" just
produce one line of output and look fine piped through column.

-Peff

^ permalink raw reply

* Re: [1.8.0] Provide proper remote ref namespaces
From: Junio C Hamano @ 2011-02-08 23:13 UTC (permalink / raw)
  To: Johan Herland
  Cc: Dmitry Potapov, git, Sverre Rabbelier, Jeff King,
	Nguyen Thai Ngoc Duy, Nicolas Pitre
In-Reply-To: <201102080915.27484.johan@herland.net>

Johan Herland <johan@herland.net> writes:

> Ah, yes, I should have been more specific:
>
>     remote.origin.fetch = ~refs/tags/*:refs/tags/*

Hmmm, I was in the vicinity of builtin/fetch.c:find_non_local_tags()
today, and I had to wonder what the implementation of this would look
like....

^ permalink raw reply

* Re: [PATCH 7/8] git-p4: decode p4 wildcard characters
From: Pete Wyckoff @ 2011-02-08 23:26 UTC (permalink / raw)
  To: Tor Arvid Lund; +Cc: git
In-Reply-To: <AANLkTi=Gah9yeYYnHPZ2Z6-OZQ2-CU5Kub=o5SqWAXht@mail.gmail.com>

torarvid@gmail.com wrote on Tue, 08 Feb 2011 10:09 +0100:
> On Sat, Feb 5, 2011 at 11:52 PM, Pete Wyckoff <pw@padd.com> wrote:
> > +    # The p4 wildcards are not allowed in filenames.  It complains
> > +    # if you try to add them, but you can override with "-f", in
> > +    # which case it translates them into %xx encoding.  Search for
> > +    # and fix just these four characters.  Do % last so it does
> > +    # not inadvertantly create new %-escapes.
> > +    def wildcard_decode(self, path):
> > +        path = path.replace("%23", "#") \
> > +                   .replace("%2A", "*") \
> 
> This probably works fine on UNIX platforms, but the asterisk '*'
> character is not allowed in windows filenames. I don't really know
> what perforce does in that scenario. Does it make the most sense to
> just keep the %2A in the filename if we are running on windows (??)

I changed it to do the "*" translation if not self.isWindows, so
%2A will remain in the filename.  Good that you noticed it.

Just for giggles, I found a windows VM to test perforce on.
Built two files with different wildcards on a unix box, then
pointed a windows client at it:

C:\DOCUME~1\ADMINI~1\DESKTOP>set P4PORT=192.168.2.1:1666

C:\DOCUME~1\ADMINI~1\DESKTOP>p4 files //depot/...
//depot/file%25percent#1 - add change 1 (binary)
//depot/file%2Astar#1 - add change 1 (binary)

C:\DOCUME~1\ADMINI~1\DESKTOP>p4 client
Client soulfree saved.

C:\DOCUME~1\ADMINI~1\DESKTOP>p4 sync
//depot/file%25percent#1 - added as c:\Documents and Settings\Administrator\Desktop\file%percent
//depot/file%2Astar#1 - added as c:\Documents and Settings\Administrator\Desktop\file*star
open for write: c:\Documents and Settings\Administrator\Desktop\file*star: The filename, directory name, or volume label syntax is incorrect.

And only the one file was synced to the windows client.  So "*" is not
well handled in perforce on windows anyway.

Docs are not helpful:

http://www.perforce.com/perforce/doc.current/manuals/cmdref/o.fspecs.html#1041962

For git, leaving a %2A in a filename is better than an error, I believe.

Thanks for the other acks.

		-- Pete

^ permalink raw reply

* Re: [PATCH v2] Add support for merging from upstream by default.
From: Junio C Hamano @ 2011-02-09  0:04 UTC (permalink / raw)
  To: Jonathan Nieder
  Cc: Jared Hance, git, Martin von Zweigbergk, Andreas Schwab,
	Bert Wesarg, Jeff King, Felipe Contreras
In-Reply-To: <20110208223359.GB17981@elie>

Jonathan Nieder <jrnieder@gmail.com> writes:

> Jared Hance wrote:

>>> Subject: Re: [PATCH v2] Add support for merging from upstream by default.

Drop full-stop '.' at the end.

>> Adds the option merge.defaultupstream to add support for merging from the
>> upstream branch by default.
>
> Could you give an example of breakage this configurability is designed
> to prevent?

I think there is no "prevent" or "breakage"; the patch is to give people a
way to turn the feature on; without the configuration, "git merge" will
keep the traditional behaviour, no?

>> +++ b/builtin/merge.c
>> @@ -37,7 +37,7 @@ struct strategy {
>>  };
>>  
>>  static const char * const builtin_merge_usage[] = {
>> -	"git merge [options] <remote>...",
>> +	"git merge [options] [<remote>...]",
>>  	"git merge [options] <msg> HEAD <remote>",
>>  	NULL
>
> Side note: these should probably say "<commit>" or "<branch>" rather
> than "<remote>".  I'm guessing the usage string comes from the days
> before the separate-remotes ref layout...

Yes, your guess is correct.

>> @@ -911,6 +934,24 @@ static int evaluate_result(void)
>>  	return cnt;
>>  }
>>  
>> +static void setup_merge_commit(struct strbuf *buf,
>> +	struct commit_list ***remotes, const char *s)
>> +{
>> +	struct object *o;
>> +	struct commit *commit;
>> +
>> +	o = peel_to_type(s, 0, NULL, OBJ_COMMIT);
>> +	if (!o)
>> +		die("%s - not something we can merge", s);
>> +	commit = lookup_commit(o->sha1);
>> +	commit->util = (void *)s;
>> +	*remotes = &commit_list_insert(commit, *remotes)->next;
>> +
>> +	strbuf_addf(buf, "GITHEAD_%s", sha1_to_hex(o->sha1));
>> +	setenv(buf->buf, s, 1);
>> +	strbuf_reset(buf);
>> +}
>
> Would be easier to review if this code movement were in a separate
> patch (separating cleanup from semantic changes).

Probably.  It is a very good idea to move this code out to its own helper
function, nevertheless; I like this part of the patch.

> Even better would be to use descriptive messages, like so:
>
>  if (head_invalid)
> 	usage_msg_opt("cannot use old-style invocation from an unborn branch",
> 		...);
>  if (!argc && ...)
> 	usage_msg_opt("no commit to merge specified", ...);

Much better.

^ permalink raw reply

* Re: [PATCH/RFC 0/7] Column output
From: Nguyen Thai Ngoc Duy @ 2011-02-09  0:13 UTC (permalink / raw)
  To: Jeff King; +Cc: git
In-Reply-To: <20110208224745.GA14190@sigill.intra.peff.net>

2011/2/9 Jeff King <peff@peff.net>:
> On Tue, Feb 08, 2011 at 10:22:14PM +0700, Nguyễn Thái Ngọc Duy wrote:
>
>> In short, the series is very simple: give porcelain commands column
>> output, just like good old "ls". There could be a few more candidates,
>> I believe René Scharfe mentioned other files in "git status".
>
> I don't really care for column output myself, so maybe you have a good
> reason why my idea won't work. But why not use the BSD column program?

Solaris did not have one last time I checked. Windows obviously does
not either, but I don't use msysgit so it does not count.
-- 
Duy

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox