From: Justin Frankel <justin@cockos•com>
To: git@vger•kernel.org
Subject: RFC: checkout/temporary branch switch restoring modification times
Date: Mon, 04 Oct 2010 00:42:00 -0400 [thread overview]
Message-ID: <4CA95B18.5090008@cockos.com> (raw)
Hello all,
I often find myself wanting to switch temporarily to another branch, and
then back to my original branch, but what I find is that my build tools
such as MSVC or Xcode) notice the file modification times changed on
the changed files, and then want to rebuild, even though the contents of
the files are the same.
I've implemented a perl script (tested on OSX and msysGit), which I've
named "git-cop" (so I can use via "git cop") to checkout,
preserving file modification times.
The use case is:
git cop master
; build
git cop some-branch-that-affects-lots-of-files
; edit some things, commit
git cop master
; build (fast, nothing changed)
If you use "checkout" instead of "cop", the final build command might
take longer, since the modification times on files may have changed.
To summarize the implementation of the script:
1) Get a list of what files will change
2) Read timestamps for changed files, updating .git/timestamp-list.txt
which is effectively an associative array of timestamps, indexed
by "blobhash:filename".
3) Call git checkout
4) Update file modification times with their new timestamps (read from
.git/timestamp-list.txt, using newblobhash:filename).
This will get slower as that text file grows, but you can periodically
remove .git/timestamp-list.txt (any time you're not in the middle of a
temporary branch switch), and it will be regenerated.
As this is a request for comments, I'd be curious if anybody has
thoughts on the best way to integrate this type of functionality into
git, or indeed if anybody else thinks it is worth including (I do find
it saves me a great deal of time, but it is easy enough to add to my git
installs, too).
Additionally, is there a better place to store repository-local
information, information which isn't terribly important and shouldn't be
copied in case of clones, etc? I figured .git/timestamp-list.txt isn't
the best place, but where would that be?
Cheers,
Justin
---------------- begin git-cop -----------------
#!/usr/bin/perl
my ($destbranch,$allargs) = ("", "");
foreach (@ARGV) {
$allargs .= " $_";
# last non-option parameter would be considered the new branch
$destbranch = $_ if ($_ !~ /^-/);
}
$destbranch eq "" and die "Usage: git-cop [checkout options] <branch>\n";
my $modf = join('',`git diff --name-only HEAD..$destbranch`);
$modf =~ s/ /\\ /g;
$modf =~ s/\n/ /g;
length($modf)>0 or exit(system("git checkout$allargs"));
chomp(my $pwd = `git rev-parse --show-toplevel`);
my $idxfile = "${pwd}/.git/timestamp-list.txt";
chdir($pwd);
my %times;
if (open(my $F, "<", $idxfile)) {
# read cached timestamps
while (<$F>) {
chomp;
my ($val, $nm) = split(/\t/, $_,2);
$nm eq "" or $val eq "" or $times{$nm} = $val;
}
close($F);
}
my $idxfile_updcnt = 0;
foreach (`git ls-tree HEAD $modf`) {
chomp;
my ($perm, $type, $hash, $fn) = split(" ",$_,4);
if ($type eq "blob") {
# add/update timestamp in cache if needed
$hash .= ":$fn";
my $mt = int ((stat("${pwd}/$fn"))[9]);
if ($mt && $mt != (int $times{$hash})) {
$times{$hash} = $mt;
$idxfile_updcnt++;
}
}
}
if ($idxfile_updcnt != 0) {
print "Saved/updated timestamps for $idxfile_updcnt files\n";
if (open(my $F, ">", $idxfile)) {
print $F "$ts\t$nm\n" while (($nm,$ts) = each(%times));
close($F);
}
}
my $rv = system("git checkout$allargs");
!$rv or exit($rv);
# restore timestamps from cache
my $update_cnt = 0;
foreach (`git ls-tree HEAD $modf`) {
chomp;
my ($perm, $type, $hash, $fn) = split(" ",$_,4);
if ($type eq "blob") {
$hash .= ":$fn";
my $tsreq = int $times{$hash};
if ($tsreq &&
$tsreq != (int ((stat("${pwd}/$fn"))[9]))) {
utime(undef,$tsreq,"${pwd}/$fn");
$update_cnt++;
}
}
}
$update_cnt < 1 or
print "Updated file timestamps for $update_cnt files\n";
exit (0);
---------------- end git-cop -----------------
next reply other threads:[~2010-10-04 4:49 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-10-04 4:42 Justin Frankel [this message]
2010-10-04 5:00 ` RFC: checkout/temporary branch switch restoring modification times Ævar Arnfjörð Bjarmason
2010-10-04 5:11 ` Jonathan Nieder
2010-10-04 14:20 ` Justin Frankel
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=4CA95B18.5090008@cockos.com \
--to=justin@cockos$(echo .)com \
--cc=git@vger$(echo .)kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox