[PATCH v2] new --dirty option for git describe

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



With the --dirty option, git describe works on HEAD but append "-dirty"
if the working tree is dirty. If the working tree is clean, nothing
is appended.

$ git describe --dirty
v1.6.5-15-gc274db7
$ echo >> Makefile
$ git describe --dirty
v1.6.5-15-gc274db7-dirty

--dirty can also be used to specify what is append if the working
tree is dirty.

$ git describe --dirty=.mod
v1.6.5-15-gc274db7.mod

Many build scripts use `git describe` to produce a version number based
on the description of HEAD (on which is based the working tree) + saying
that if the working tree is dirty or no.
This patch helps the writing of such scripts since `git describe --dirty`
do directly the intended thing.

Alternatives specifications:

1 Describe the working tree by default and describe HEAD only if "HEAD"
  is explicitly specified
Pro: does the right thing by default (both for users and for scripts)
Pro: is coherent with other git commands that works on the working tree
     by default
Con: breaks existing scripts (since the world is not ideal)

2 Use --worktree instead of --dirty
Pro: does what it says: "git describe --worktree" will describe the
     working three
Con: is incoherent with other commands that do not require a --worktree
     option to work on the working tree
Con: unusable with an optional value: "git describe --worktree=.mod"
     is quite unintuitive.

3 Use --dirty as in this patch
Pro: make sense to specify an optional value (what the dirty mark is)
Pro: do not have any of the big cons of previous alternatives
     * does not break scripts
     * is not inconsistent with other git commands
Pro: has an easy fallback to alternative 1 if the world become suddenly
     ideal, or at least allows some kind of future transition plan if
     people *really* bother:
     1- ask that scripts use either "git describe HEAD" or
        "git describe --dirty" (no more "git describe")
     2- change default
     Once the transition is done, the role of the --dirty option will
     just be the way to specify an alternative mark (and a noop if alone)

Signed-off-by: Jean Privat <jean@xxxxxxxxx>

---

I tried to integrate the points of view of both Junio and Shawn.
However, I am not sure that what I propose is the right solution.

-J-
---
 Documentation/git-describe.txt |    6 ++++++
 builtin-describe.c             |   25 ++++++++++++++++++++++++-
 t/t6120-describe.sh            |   15 +++++++++++++++
 3 files changed, 45 insertions(+), 1 deletions(-)

diff --git a/Documentation/git-describe.txt b/Documentation/git-describe.txt
index b231dbb..5253d86 100644
--- a/Documentation/git-describe.txt
+++ b/Documentation/git-describe.txt
@@ -9,6 +9,7 @@ git-describe - Show the most recent tag that is
reachable from a commit
 SYNOPSIS
 --------
 'git describe' [--all] [--tags] [--contains] [--abbrev=<n>] <committish>...
+'git describe' [--all] [--tags] [--contains] [--abbrev=<n>] --dirty[=<mark>]

 DESCRIPTION
 -----------
@@ -27,6 +28,11 @@ OPTIONS
 <committish>...::
 	Committish object names to describe.

+--dirty[=<mark>]::
+	Describe the working tree.
+	It means describe HEAD and appends <mark> (`-dirty` by
+	default) if the working tree is dirty.
+
 --all::
 	Instead of using only the annotated tags, use any ref
 	found in `.git/refs/`.  This option enables matching
diff --git a/builtin-describe.c b/builtin-describe.c
index df67a73..84af981 100644
--- a/builtin-describe.c
+++ b/builtin-describe.c
@@ -5,12 +5,14 @@
 #include "builtin.h"
 #include "exec_cmd.h"
 #include "parse-options.h"
+#include "diff.h"

 #define SEEN		(1u<<0)
 #define MAX_TAGS	(FLAG_BITS - 1)

 static const char * const describe_usage[] = {
 	"git describe [options] <committish>*",
+	"git describe [options] --dirty",
 	NULL
 };

@@ -23,6 +25,13 @@ static int max_candidates = 10;
 static int found_names;
 static const char *pattern;
 static int always;
+static const char *dirty;
+
+/* diff-index command arguments to check if working tree is dirty. */
+static const char *diff_index_args[] = {
+	"diff-index", "--quiet", "HEAD", "--", NULL
+};
+

 struct commit_name {
 	struct tag *tag;
@@ -208,6 +217,8 @@ static void describe(const char *arg, int last_one)
 		display_name(n);
 		if (longformat)
 			show_suffix(0, n->tag ? n->tag->tagged->sha1 : sha1);
+		if (dirty)
+			printf("%s", dirty);
 		printf("\n");
 		return;
 	}
@@ -265,7 +276,10 @@ static void describe(const char *arg, int last_one)
 	if (!match_cnt) {
 		const unsigned char *sha1 = cmit->object.sha1;
 		if (always) {
-			printf("%s\n", find_unique_abbrev(sha1, abbrev));
+			printf("%s", find_unique_abbrev(sha1, abbrev));
+			if (dirty)
+				printf("%s", dirty);
+			printf("\n");
 			return;
 		}
 		die("cannot describe '%s'", sha1_to_hex(sha1));
@@ -300,6 +314,8 @@ static void describe(const char *arg, int last_one)
 	display_name(all_matches[0].name);
 	if (abbrev)
 		show_suffix(all_matches[0].depth, cmit->object.sha1);
+	if (dirty)
+		printf("%s", dirty);
 	printf("\n");

 	if (!last_one)
@@ -324,6 +340,9 @@ int cmd_describe(int argc, const char **argv,
const char *prefix)
 			   "only consider tags matching <pattern>"),
 		OPT_BOOLEAN(0, "always",     &always,
 			   "show abbreviated commit object as fallback"),
+		{OPTION_STRING, 0, "dirty",       &dirty, "mark",
+			   "append <mark> on dirty working tree (default: \"-dirty\")",
+			   PARSE_OPT_OPTARG, NULL, "-dirty"},
 		OPT_END(),
 	};

@@ -360,7 +379,11 @@ int cmd_describe(int argc, const char **argv,
const char *prefix)
 	}

 	if (argc == 0) {
+		if (dirty && !cmd_diff_index(ARRAY_SIZE(diff_index_args) - 1,
diff_index_args, prefix))
+			dirty = NULL;
 		describe("HEAD", 1);
+	} else if (dirty) {
+		die("--dirty is incompatible with committishes");
 	} else {
 		while (argc-- > 0) {
 			describe(*argv++, argc == 0);
diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh
index 8c7e081..ee38f34 100755
--- a/t/t6120-describe.sh
+++ b/t/t6120-describe.sh
@@ -123,6 +123,21 @@ test_expect_success 'rename tag Q back to A' '
 test_expect_success 'pack tag refs' 'git pack-refs'
 check_describe A-* HEAD

+check_describe "A-*[0-9a-f]" --dirty
+
+test_expect_success 'set-up dirty working tree' '
+	echo >>file
+'
+
+check_describe "A-*[0-9a-f]-dirty" --dirty
+
+check_describe "A-*[0-9a-f].mod" --dirty=.mod
+
+test_expect_success 'describe --dirty HEAD' '
+	git describe --dirty HEAD
+	test $? != 0
+'
+
 test_expect_success 'set-up matching pattern tests' '
 	git tag -a -m test-annotated test-annotated &&
 	echo >>file &&
-- 
1.6.5
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]