Junio C Hamano <junkio@xxxxxxx> wrote: > Linus Torvalds <torvalds@xxxxxxxx> writes: > > > I actually disagree with Junio - I think the logging the name made sense. > > If you have a shared repo with multiple people pushing to the same branch, > > it's interesting to see who does the pushing. > > Yes, I agree recording that information is interesting. > > My comment was about how it is recorded. In the local case > GIT_COMMITTER_IDENT is what you want as Shawn did in his > original proposal, but remote "pushing into shared repository" > case I do not think it is available in general. > > Well, at least that was what I was thinking when I made that > comment. However, > > If the pushers arrange to have appropriate environment variables > while receive-pack does its work (.git/config in the target > repository is not an appropriate place to get user.* settings > from in a shared setting), what you say makes perfect sense. > > Having the usual enviornment available would be handy to make > the hooks on the receiving end to do useful things anyway, so I > retract that suggestion. > > > I also think it might be good to save the oldsha1 value. Yes, it _should_ > > always be the previous sha1 logged, but it's interesting to see in case it > > isn't (ie the ref was updated some other way), and it's also interesting > > for the first entry after logging has been enabled. > > > > Linue > > Yes, and also what user-level command was used to cause update > the ref; was it a merge from remote, own commit, rewind/rebase? > > Junia > > ;-) > New version of the patch below; this patch superceeds the prior two. The format now includes the old sha1 and committer ident, and does not write a log record if the update-ref is pointless. Hmm, why does update-ref do a pointless update? Now the problem with this patch is it doesn't append to the log in the case of upload-pack or fetch; nor does it record what user level command caused the update. [spearce@pb15 git]$ grep update-ref *.sh *.perl *.py | wc -l 20 Hmm. That's easy enough to fix. Anyone up for a '-m foo' comment switch to update-ref from the higher-level tools such that foo appears as part of the log line? I'll be offline for a few hours but can work on this some more later tonight. --> - Log ref updates to logs/refs/<ref> If config parameter core.logRefUpdates is true then append a line to .git/logs/refs/<ref> whenever git-update-ref <ref> is executed. Each log line contains the following information: oldsha1 <SP> newsha1 <SP> committer <LF> where committer is the current user, date, time and timezone in the standard GIT ident format. If the caller is unable to append to the log file then git-update-ref will fail without updating <ref>. --- Documentation/config.txt | 7 ++++++ Documentation/git-update-ref.txt | 19 +++++++++++++++ cache.h | 1 + config.c | 5 ++++ environment.c | 1 + update-ref.c | 48 ++++++++++++++++++++++++++++++++++++-- 6 files changed, 78 insertions(+), 3 deletions(-) 898e33d9c2def73296697d65dff0676d96adb5d8 diff --git a/Documentation/config.txt b/Documentation/config.txt index d1a4bec..f06695c 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -70,6 +70,13 @@ core.preferSymlinkRefs:: This is sometimes needed to work with old scripts that expect HEAD to be a symbolic link. +core.logRefUpdates:: + If true, `git-update-ref` will append a line to + "$GIT_DIR/logs/<ref>" listing the new SHA1 and the date/time + of the update. This information can be used to determine + what commit was the tip of a branch "2 days ago". This value + is false by default (no logging). + core.repositoryFormatVersion:: Internal variable identifying the repository format and layout version. diff --git a/Documentation/git-update-ref.txt b/Documentation/git-update-ref.txt index 475237f..edd39d3 100644 --- a/Documentation/git-update-ref.txt +++ b/Documentation/git-update-ref.txt @@ -49,6 +49,25 @@ for reading but not for writing (so we'l ref symlink to some other tree, if you have copied a whole archive by creating a symlink tree). +Logging Updates +--------------- +If config parameter "core.logRefUpdates" is true then +`git-update-ref` will append a line to the log file +"$GIT_DIR/logs/<ref>" (dereferencing all symbolic refs before +creating the log name) describing the change in ref value. Log lines +are formatted as: + + . oldsha1 SP newsha1 SP committer LF ++ +Where "oldsha1" is the 40 character hexadecimal value previously +stored in <ref>, "newsha1" is the 40 character hexadecimal value of +<newvalue> and "committer" is the committer's name, email address +and date in the standard GIT committer ident format. + +An update will fail (without changing <ref>) if the current user is +unable to create a new log file, append to the existing log file +or does not have committer information available. + Author ------ Written by Linus Torvalds <torvalds@xxxxxxxx>. diff --git a/cache.h b/cache.h index b1300cd..887ce20 100644 --- a/cache.h +++ b/cache.h @@ -171,6 +171,7 @@ extern void rollback_index_file(struct c extern int trust_executable_bit; extern int assume_unchanged; extern int prefer_symlink_refs; +extern int log_ref_updates; extern int warn_ambiguous_refs; extern int diff_rename_limit_default; extern int shared_repository; diff --git a/config.c b/config.c index 0f518c9..f8a814e 100644 --- a/config.c +++ b/config.c @@ -232,6 +232,11 @@ int git_default_config(const char *var, return 0; } + if (!strcmp(var, "core.logrefupdates")) { + log_ref_updates = git_config_bool(var, value); + return 0; + } + if (!strcmp(var, "core.warnambiguousrefs")) { warn_ambiguous_refs = git_config_bool(var, value); return 0; diff --git a/environment.c b/environment.c index 444c99e..437266e 100644 --- a/environment.c +++ b/environment.c @@ -14,6 +14,7 @@ char git_default_name[MAX_GITNAME]; int trust_executable_bit = 1; int assume_unchanged = 0; int prefer_symlink_refs = 0; +int log_ref_updates = 0; int warn_ambiguous_refs = 1; int repository_format_version = 0; char git_commit_encoding[MAX_ENCODING_LENGTH] = "utf-8"; diff --git a/update-ref.c b/update-ref.c index fd48742..64fc3db 100644 --- a/update-ref.c +++ b/update-ref.c @@ -22,7 +22,7 @@ int main(int argc, char **argv) const char *refname, *value, *oldval, *path; char *lockpath; unsigned char sha1[20], oldsha1[20], currsha1[20]; - int fd, written; + int fd, written, pfxlen; setup_git_directory(); git_config(git_default_config); @@ -38,7 +38,9 @@ int main(int argc, char **argv) if (oldval && get_sha1(oldval, oldsha1)) die("%s: not a valid old SHA1", oldval); - path = resolve_ref(git_path("%s", refname), currsha1, !!oldval); + path = git_path("%s", refname); + pfxlen = strlen(path) - strlen(refname); + path = resolve_ref(path, currsha1, !!oldval); if (!path) die("No such ref: %s", refname); @@ -50,7 +52,7 @@ int main(int argc, char **argv) exit(0); } path = strdup(path); - lockpath = mkpath("%s.lock", path); + lockpath = strdup(mkpath("%s.lock", path)); if (safe_create_leading_directories(lockpath) < 0) die("Unable to create all of %s", lockpath); @@ -75,6 +77,46 @@ int main(int argc, char **argv) } /* + * Write to the log if logging of ref updates is enabled + */ + if (log_ref_updates && memcmp(currsha1, sha1, 20)) { + char *logrec, *logpath; + const char *comitter; + unsigned maxlen, len; + int logfd; + + setup_ident(); + comitter = git_committer_info(1); + maxlen = strlen(comitter) + 2*40 + 4; + logrec = xmalloc(maxlen); + len = snprintf(logrec, maxlen, "%s %s %s\n", + sha1_to_hex(currsha1), + sha1_to_hex(sha1), + comitter); + if (len >= maxlen) { + unlink(lockpath); + die("Internal error formatting log record."); + } + + logpath = git_path("logs/%s", path + pfxlen); + if (safe_create_leading_directories(logpath) < 0) { + unlink(lockpath); + die("Unable to create all of %s", logpath); + } + logfd = open(logpath, O_CREAT | O_APPEND | O_WRONLY, 0666); + if (logfd < 0) { + unlink(lockpath); + die("Unable to append to %s", logpath); + } + written = write(logfd, logrec, len); + if (written != len) { + unlink(lockpath); + die("Unable to append to %s", logpath); + } + close(logfd); + } + + /* * Finally, replace the old ref with the new one */ if (rename(lockpath, path) < 0) { -- 1.3.2.g7278 - : 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