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@xxxxxxxx> --- 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 - 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