All of lore.kernel.org
 help / color / mirror / Atom feed
From: Robert Fitzsimons <robfitz@273k.net>
To: git@vger.kernel.org
Subject: [RFC/PATCH] Add builtin git-last-modified.
Date: Mon, 1 Jan 2007 07:55:15 +0000	[thread overview]
Message-ID: <20070101075515.GK6558@localhost> (raw)

This is a plumbing command which can be used by gitweb.  It will scan
a list of commits and/or refs and return the time in seconds for the
youngest commit.  This value can then be used to generate and check
the Last-Modified and Is-Modified-Since HTTP headers.

Signed-off-by: Robert Fitzsimons <robfitz@273k.net>
---


The following two commands lines are similar:

$ git for-each-ref --count=1 --sort=-committerdate '--format=%(committerdate)' refs/heads
$ git last-modified --branches

The last-modified version is a bit faster (5-10%).

I'm not 100% sure how this command and if this command should be used
by gitweb.  But I'll post the patch anyway for comments.

Robert



 .gitignore                          |    1 +
 Documentation/git-last-modified.txt |   49 ++++++++++++++++++++++++++++
 Makefile                            |    3 +-
 builtin-last-modified.c             |   61 +++++++++++++++++++++++++++++++++++
 builtin.h                           |    1 +
 git.c                               |    1 +
 t/t3810-last-modified.sh            |   57 ++++++++++++++++++++++++++++++++
 7 files changed, 172 insertions(+), 1 deletions(-)

diff --git a/.gitignore b/.gitignore
index 2904f12..ffca6c5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -58,6 +58,7 @@ git-lost-found
 git-ls-files
 git-ls-remote
 git-ls-tree
+git-last-modified
 git-mailinfo
 git-mailsplit
 git-merge
diff --git a/Documentation/git-last-modified.txt b/Documentation/git-last-modified.txt
new file mode 100644
index 0000000..4584b5d
--- /dev/null
+++ b/Documentation/git-last-modified.txt
@@ -0,0 +1,49 @@
+git-last-modified(1)
+================
+
+NAME
+----
+git-last-modified - Get the last modified time in seconds
+
+
+SYNOPSIS
+--------
+'git-last-modified' [ \--all ]
+		    [ \--branches ]
+		    [ \--tags ]
+		    [ \--remotes ]
+		    <commmit>...
+
+DESCRIPTION
+-----------
+
+Get the last modified time in seconds for the youngest commit object
+based on the search criteria.  The time value is from the 'commit'
+header of the commit object, ignoring the timezone.  The time is
+formatted as an ASCII decimal number and is the number of seconds
+since epoch.
+
+This is a plumbing command used by gitweb to generate and check the
+Last-Modified and Is-Modified-Since HTTP headers.
+
+OPTIONS
+-------
+--all::
+	Search all refs found in `$GIT_DIR/refs`.
+
+--branches::
+	Search branch refs found in `$GIT_DIR/refs/heads`.
+
+--tags::
+	Search tag refs found in `$GIT_DIR/refs/tags`.
+
+--remotes::
+	Search remote refs found in `$GIT_DIR/refs/remotes`.
+
+<commit>...::
+	Search list of commits and refs.
+
+GIT
+---
+Part of the gitlink:git[7] suite
+
diff --git a/Makefile b/Makefile
index fa1a022..1f169ac 100644
--- a/Makefile
+++ b/Makefile
@@ -312,7 +312,8 @@ BUILTIN_OBJS = \
 	builtin-verify-pack.o \
 	builtin-write-tree.o \
 	builtin-show-ref.o \
-	builtin-pack-refs.o
+	builtin-pack-refs.o \
+	builtin-last-modified.o
 
 GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
 EXTLIBS = -lz
diff --git a/builtin-last-modified.c b/builtin-last-modified.c
new file mode 100644
index 0000000..38cfb80
--- /dev/null
+++ b/builtin-last-modified.c
@@ -0,0 +1,61 @@
+#include "cache.h"
+#include "commit.h"
+#include "refs.h"
+#include "builtin.h"
+
+static int lastmod_date(const unsigned char *sha1, unsigned long *date)
+{
+	struct commit *commit = lookup_commit_reference_gently(sha1, 1);
+
+	if (!commit)
+		return 1;
+
+	if (commit->date > *date)
+		*date = commit->date;
+
+	return 0;
+}
+
+static int process_ref(const char *refname, const unsigned char *sha1, int flags, void *cb_data)
+{
+	return lastmod_date(sha1, (unsigned long *)cb_data);
+}
+
+int cmd_last_modified(int argc, const char **argv, const char *prefix)
+{
+	int i;
+	unsigned char sha1[20];
+	unsigned long date = 0;
+
+	git_config(git_default_config);
+
+	for (i = 1; i < argc; i++) {
+		const char *arg = argv[i];
+
+		if (!strcmp(arg, "--all")) {
+			for_each_ref(process_ref, &date);
+			continue;
+		}
+		if (!strcmp(arg, "--branches")) {
+			for_each_branch_ref(process_ref, &date);
+			continue;
+		}
+		if (!strcmp(arg, "--tags")) {
+			for_each_tag_ref(process_ref, &date);
+			continue;
+		}
+		if (!strcmp(arg, "--remotes")) {
+			for_each_remote_ref(process_ref, &date);
+			continue;
+		}
+
+		if (get_sha1(arg, sha1))
+			die("last-modified: could not get sha1 for '%s'", arg);
+		if (lastmod_date(sha1, &date))
+			die("last-modified: bad revision '%s'", arg);
+	}
+
+	printf("%lu\n", date);
+
+	return 0;
+}
diff --git a/builtin.h b/builtin.h
index df72d09..862cadb 100644
--- a/builtin.h
+++ b/builtin.h
@@ -75,5 +75,6 @@ extern int cmd_write_tree(int argc, const char **argv, const char *prefix);
 extern int cmd_verify_pack(int argc, const char **argv, const char *prefix);
 extern int cmd_show_ref(int argc, const char **argv, const char *prefix);
 extern int cmd_pack_refs(int argc, const char **argv, const char *prefix);
+extern int cmd_last_modified(int argc, const char **argv, const char *prefix);
 
 #endif
diff --git a/git.c b/git.c
index c82ca45..e6242e6 100644
--- a/git.c
+++ b/git.c
@@ -269,6 +269,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
 		{ "verify-pack", cmd_verify_pack },
 		{ "show-ref", cmd_show_ref, RUN_SETUP },
 		{ "pack-refs", cmd_pack_refs, RUN_SETUP },
+		{ "last-modified", cmd_last_modified, RUN_SETUP },
 	};
 	int i;
 
diff --git a/t/t3810-last-modified.sh b/t/t3810-last-modified.sh
new file mode 100755
index 0000000..d85283e
--- /dev/null
+++ b/t/t3810-last-modified.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+
+test_description='git-last-modified'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+    for n in 1 2 3 4 5 ; do \
+        echo $n > a ; \
+        git-add a ; \
+        git-commit -m "$n" ; \
+    done ; \
+    git-tag -m "t1" t1 ; \
+    git-checkout -b o ; \
+    for n in o1 o1 o3 o4 o5 ; do \
+        echo $n > b ; \
+        git-add b ; \
+        git-commit -m "$n" ; \
+    done ; \
+    git-tag -m "t2" t2 ; \
+    git-checkout master
+'
+
+test_expect_success 'no options' '
+    test $(git-last-modified) -eq 0
+'
+
+test_expect_success 'rev HEAD' '
+    test $(git-last-modified HEAD) -gt 0 &&
+    test $(git-last-modified refs/heads/master) -gt 0 &&
+    test $(git-last-modified --all) -gt 0 &&
+    test $(git-last-modified --branches) -gt 0 &&
+    test $(git-last-modified --tags) -gt 0 &&
+    test $(git-last-modified --remotes) -eq 0
+'
+
+test_expect_success 'rev master -lt o' '
+    test $(git-last-modified master) -lt $(git-last-modified o)
+'
+
+test_expect_success 'mixed --branches HEAD t1 o' '
+    test $(git-last-modified --branches HEAD t1 o) -gt 0
+'
+
+test_expect_failure 'bad sha1' '
+    git-last-modified 000000
+'
+
+test_expect_failure 'bad rev' '
+    git-last-modified xyz
+'
+
+test_expect_failure 'bad --branches rev' '
+    git-last-modified xyz
+'
+
+test_done
-- 
1.5.0.rc0.g2708-dirty

                 reply	other threads:[~2007-01-01  7:55 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20070101075515.GK6558@localhost \
    --to=robfitz@273k.net \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.