* Re: [PATCH v2] Replace instances of export VAR=VAL with VAR=VAL; export VAR
From: David Kastrup @ 2007-11-29 10:17 UTC (permalink / raw)
To: Johannes Sixt
Cc: Junio C Hamano, Johannes Schindelin, Wincent Colaiuta,
Benoit Sigoure, Git Mailing List
In-Reply-To: <474E6CC8.8000301@viscovery.net>
Johannes Sixt <j.sixt@viscovery.net> writes:
>> What problem are we talking about exactly, and with what shell?
>
> $ export foo="bar baz"
> $ bash
> bash$ export JUNK=$foo
> bash$ sh -c 'echo "$JUNK"'
> bar baz
> bash$ exit
> exit
> $ ash
> ash$ export JUNK=$foo
> ash$ sh -c 'echo "$JUNK"'
> bar
> ash$ exit
>
> The problem is $foo not being quoted on the RHS of the assignment of
> the export command: bash doesn't word-split, but ash does. Hence, *if*
> export VAR=VAL is used, always quote VAL.
I much prefer the quoting solution over the quite more invasive rewrites
proposed here.
--
David Kastrup, Kriemhildstr. 15, 44793 Bochum
^ permalink raw reply
* [PATCH] per-directory-exclude: lazily read .gitignore files
From: Junio C Hamano @ 2007-11-29 10:17 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Git Mailing List
In-Reply-To: <7vr6i9y6ju.fsf@gitster.siamese.dyndns.org>
Operations that walk directories or trees, which potentially need to
consult the .gitignore files, used to always try to open the .gitignore
file every time they entered a new directory, even when they ended up
not needing to call excluded() function to see if a path in the
directory is ignored.
This changes the directory walking API to remove the need to call these
two functions. Instead, the directory walk data structure caches the
data used by excluded() function the last time, and lazily reuses it as
much as possible. Among the data the last check used, the ones from
deeper directories that the path we are checking is outside are
discarded, data from the common leading directories are reused, and then
the directories between the common directory and the directory the path
being checked is in are checked for .gitignore file. This is very
similar to the way gitattributes are handled.
This API change also fixes "ls-files -c -i", which called excluded()
without setting up the gitignore data via the old push/pop functions.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
Junio C Hamano <gitster@pobox.com> writes:
> Linus Torvalds <torvalds@linux-foundation.org> writes:
>
>> Less than a hundredth of a second may not sound much, but when we have
>> 1700+ directories in the kernel trees, doing that for each possible
>> .gitignore file is really really expensive!
>
> The only thing that wants to use excluded() in the unpack_trees()
> codepath is the code to allow overwriting an existing, untracked file in
> verify_absent(). When we find an untracked file at the same path as we
> are just trying to check out a file, we allow overwriting it only if
> that file is "ignored".
> ...
> The newer gitattributes subsystem maintains a similar per-directory data
> structure but this is purely done on-demand; until somebody asks "what
> are the attrs for this path", we do not read .gitattributes file. We
> should be able to restructure exclude-per-directory code in a similar
> way.
I haven't seriously benched this, other than the same read-tree test
you mentioned. With the good locality the directory walking (both by
read_directory() aka ls-files and unpack_trees() aka read-tree) tends
to have, checks for paths from the same directory come next to each
other, and that seems to help.
dir.c | 103 +++++++++++++++++++++++++++++---------------------------
dir.h | 32 ++++++++++-------
unpack-trees.c | 6 ---
3 files changed, 72 insertions(+), 69 deletions(-)
diff --git a/dir.c b/dir.c
index 7c97483..d448902 100644
--- a/dir.c
+++ b/dir.c
@@ -151,6 +151,7 @@ void add_exclude(const char *string, const char *base,
static int add_excludes_from_file_1(const char *fname,
const char *base,
int baselen,
+ char **buf_p,
struct exclude_list *which)
{
struct stat st;
@@ -171,6 +172,8 @@ static int add_excludes_from_file_1(const char *fname,
goto err;
close(fd);
+ if (buf_p)
+ *buf_p = buf;
buf[size++] = '\n';
entry = buf;
for (i = 0; i < size; i++) {
@@ -192,31 +195,63 @@ static int add_excludes_from_file_1(const char *fname,
void add_excludes_from_file(struct dir_struct *dir, const char *fname)
{
- if (add_excludes_from_file_1(fname, "", 0,
+ if (add_excludes_from_file_1(fname, "", 0, NULL,
&dir->exclude_list[EXC_FILE]) < 0)
die("cannot use %s as an exclude file", fname);
}
-int push_exclude_per_directory(struct dir_struct *dir, const char *base, int baselen)
+static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
{
- char exclude_file[PATH_MAX];
- struct exclude_list *el = &dir->exclude_list[EXC_DIRS];
- int current_nr = el->nr;
-
- if (dir->exclude_per_dir) {
- memcpy(exclude_file, base, baselen);
- strcpy(exclude_file + baselen, dir->exclude_per_dir);
- add_excludes_from_file_1(exclude_file, base, baselen, el);
+ struct exclude_list *el;
+ struct exclude_stack *stk = NULL;
+ int current;
+
+ if ((!dir->exclude_per_dir) ||
+ (baselen + strlen(dir->exclude_per_dir) >= PATH_MAX))
+ return; /* too long a path -- ignore */
+
+ /* Pop the ones that are not the prefix of the path being checked. */
+ el = &dir->exclude_list[EXC_DIRS];
+ while ((stk = dir->exclude_stack) != NULL) {
+ if (stk->baselen <= baselen &&
+ !strncmp(dir->basebuf, base, stk->baselen))
+ break;
+ dir->exclude_stack = stk->prev;
+ while (stk->exclude_ix < el->nr)
+ free(el->excludes[--el->nr]);
+ free(stk->filebuf);
+ free(stk);
}
- return current_nr;
-}
-void pop_exclude_per_directory(struct dir_struct *dir, int stk)
-{
- struct exclude_list *el = &dir->exclude_list[EXC_DIRS];
+ /* Read from the parent directories and push them down. */
+ current = stk ? stk->baselen : -1;
+ while (current < baselen) {
+ struct exclude_stack *stk = xcalloc(1, sizeof(*stk));
+ const char *cp;
- while (stk < el->nr)
- free(el->excludes[--el->nr]);
+ if (current < 0) {
+ cp = base;
+ current = 0;
+ }
+ else {
+ cp = strchr(base + current + 1, '/');
+ if (!cp)
+ die("oops in prep_exclude");
+ cp++;
+ }
+ stk->prev = dir->exclude_stack;
+ stk->baselen = cp - base;
+ stk->exclude_ix = el->nr;
+ memcpy(dir->basebuf + current, base + current,
+ stk->baselen - current);
+ strcpy(dir->basebuf + stk->baselen, dir->exclude_per_dir);
+ add_excludes_from_file_1(dir->basebuf,
+ dir->basebuf, stk->baselen,
+ &stk->filebuf, el);
+ dir->exclude_stack = stk;
+ current = stk->baselen;
+ }
+ dir->basebuf[baselen] = '\0';
}
/* Scan the list and let the last match determines the fate.
@@ -283,6 +318,7 @@ int excluded(struct dir_struct *dir, const char *pathname)
const char *basename = strrchr(pathname, '/');
basename = (basename) ? basename+1 : pathname;
+ prep_exclude(dir, pathname, basename-pathname);
for (st = EXC_CMDL; st <= EXC_FILE; st++) {
switch (excluded_1(pathname, pathlen, basename, &dir->exclude_list[st])) {
case 0:
@@ -500,13 +536,10 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
int contents = 0;
if (fdir) {
- int exclude_stk;
struct dirent *de;
char fullname[PATH_MAX + 1];
memcpy(fullname, base, baselen);
- exclude_stk = push_exclude_per_directory(dir, base, baselen);
-
while ((de = readdir(fdir)) != NULL) {
int len, dtype;
int exclude;
@@ -580,8 +613,6 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
}
exit_early:
closedir(fdir);
-
- pop_exclude_per_directory(dir, exclude_stk);
}
return contents;
@@ -650,37 +681,9 @@ static void free_simplify(struct path_simplify *simplify)
int read_directory(struct dir_struct *dir, const char *path, const char *base, int baselen, const char **pathspec)
{
struct path_simplify *simplify = create_simplify(pathspec);
- char *pp = NULL;
-
- /*
- * Make sure to do the per-directory exclude for all the
- * directories leading up to our base.
- */
- if (baselen) {
- if (dir->exclude_per_dir) {
- char *p;
- pp = xmalloc(baselen+1);
- memcpy(pp, base, baselen+1);
- p = pp;
- while (1) {
- char save = *p;
- *p = 0;
- push_exclude_per_directory(dir, pp, p-pp);
- *p++ = save;
- if (!save)
- break;
- p = strchr(p, '/');
- if (p)
- p++;
- else
- p = pp + baselen;
- }
- }
- }
read_directory_recursive(dir, path, base, baselen, 0, simplify);
free_simplify(simplify);
- free(pp);
qsort(dir->entries, dir->nr, sizeof(struct dir_entry *), cmp_name);
qsort(dir->ignored, dir->ignored_nr, sizeof(struct dir_entry *), cmp_name);
return dir->nr;
diff --git a/dir.h b/dir.h
index 82009dc..d8814dc 100644
--- a/dir.h
+++ b/dir.h
@@ -1,17 +1,6 @@
#ifndef DIR_H
#define DIR_H
-/*
- * We maintain three exclude pattern lists:
- * EXC_CMDL lists patterns explicitly given on the command line.
- * EXC_DIRS lists patterns obtained from per-directory ignore files.
- * EXC_FILE lists patterns from fallback ignore files.
- */
-#define EXC_CMDL 0
-#define EXC_DIRS 1
-#define EXC_FILE 2
-
-
struct dir_entry {
unsigned int len;
char name[FLEX_ARRAY]; /* more */
@@ -34,6 +23,13 @@ struct exclude_list {
} **excludes;
};
+struct exclude_stack {
+ struct exclude_stack *prev;
+ char *filebuf;
+ int baselen;
+ int exclude_ix;
+};
+
struct dir_struct {
int nr, alloc;
int ignored_nr, ignored_alloc;
@@ -48,6 +44,18 @@ struct dir_struct {
/* Exclude info */
const char *exclude_per_dir;
struct exclude_list exclude_list[3];
+ /*
+ * We maintain three exclude pattern lists:
+ * EXC_CMDL lists patterns explicitly given on the command line.
+ * EXC_DIRS lists patterns obtained from per-directory ignore files.
+ * EXC_FILE lists patterns from fallback ignore files.
+ */
+#define EXC_CMDL 0
+#define EXC_DIRS 1
+#define EXC_FILE 2
+
+ struct exclude_stack *exclude_stack;
+ char basebuf[PATH_MAX];
};
extern int common_prefix(const char **pathspec);
@@ -58,8 +66,6 @@ extern int common_prefix(const char **pathspec);
extern int match_pathspec(const char **pathspec, const char *name, int namelen, int prefix, char *seen);
extern int read_directory(struct dir_struct *, const char *path, const char *base, int baselen, const char **pathspec);
-extern int push_exclude_per_directory(struct dir_struct *, const char *, int);
-extern void pop_exclude_per_directory(struct dir_struct *, int);
extern int excluded(struct dir_struct *, const char *);
extern void add_excludes_from_file(struct dir_struct *, const char *fname);
diff --git a/unpack-trees.c b/unpack-trees.c
index aea16ad..e9eb795 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -71,12 +71,8 @@ static int unpack_trees_rec(struct tree_entry_list **posns, int len,
int remove;
int baselen = strlen(base);
int src_size = len + 1;
- int i_stk = i_stk;
int retval = 0;
- if (o->dir)
- i_stk = push_exclude_per_directory(o->dir, base, strlen(base));
-
do {
int i;
const char *first;
@@ -255,8 +251,6 @@ static int unpack_trees_rec(struct tree_entry_list **posns, int len,
} while (1);
leave_directory:
- if (o->dir)
- pop_exclude_per_directory(o->dir, i_stk);
return retval;
}
--
1.5.3.6.2064.g2e22f
^ permalink raw reply related
* Re: Adding push configuration to .git/config
From: Nico -telmich- Schottelius @ 2007-11-28 22:15 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Steffen Prohaska, Junio C Hamano, git
In-Reply-To: <Pine.LNX.4.64.0711221120300.27959@racer.site>
[-- Attachment #1: Type: text/plain, Size: 1549 bytes --]
Hello guys,
I'm replying a bit late, had much to work in the last days.
I really like some ideas discussed here and want to state that
- "git push" without options is much easier and does nothing wrong,
if you configured the branch.$name.pushto correctly
- I also think that having support for multiple push destinations
per branch would be excellent for a distributed version control system
like git
- doing 'git push origin master:myremote/myname' just covers to much
redundant data, which imho can (but not must) be put into .git/config
- I don't care about the configuration names, we can even stick to
"merge" for now and add simply add "push" and rename them in git 2.x
I currently would like this variant mostly, allowing high flexibility:
--------------------------------------------------------------------------------
[remote "myremote"]
url = git+ssh://.... # no change
ref = refs/heads/ # renamed fetch = ...
# that way we can use the remote for fetch and push:
[branch "master"]
merge = myremote
push = myremote
push = anotherremote
[branch "otherbranch"]
merge = otherremote
push = otherremote
push = classmate
push = myremote
--------------------------------------------------------------------------------
What do you think about that approach?
Sincerly
Nico
--
Think about Free and Open Source Software (FOSS).
http://nico.schottelius.org/documentations/foss/the-term-foss/
PGP: BFE4 C736 ABE5 406F 8F42 F7CF B8BE F92A 9885 188C
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH/RFC] Teach repack to optionally retain otherwise lost objects
From: Johannes Schindelin @ 2007-11-29 11:57 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Johannes Sixt, git
In-Reply-To: <7vaboxy3va.fsf@gitster.siamese.dyndns.org>
Hi,
On Wed, 28 Nov 2007, Junio C Hamano wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> > Besides, a completely different idea just struck me: before
> > repacking, .git/objects/pack/* could be _hard linked_ to the
> > forkee's object stores. Then nothing in git-repack's code
> > needs to be changed.
> >
> > Oh, well. I just wasted 1.5 hours.
>
> Your 1.5 hours was spent wisely to come up with that idea ;-).
Thanks ;-)
> To make sure I understand your idea correctly, the procedure to repack a
> repository in a fork-friendly way is:
>
> (1) find the project directly forked from you;
>
> (2) hardlink all packs under your object store to their object store;
>
> (3) repack -a -l and prune.
Yep.
> I think that would work as long as you do the above as a unit and handle
> one repository at a time.
Exactly. See
http://repo.or.cz/w/repo.git?a=commitdiff;h=fba501deabd349afbe3b8bf89f385889889e04ac
for a tired proposal.
Note that "prune" is not (yet) an option, since it could possibly destroy
objects which are needed in an ongoing push operation.
However, we could do exactly the same as with reflogs: introduce a grace
period (with loose objects, we can use the ctime...)
> Otherwise I think you risk losing necessary objects when hierarchical
> forks are involved. E.g. if you have a project X that has a fork Y
> which in turn has fork Z.
Well, in theory you could also iterate over all projects and hard link the
packs/objects of their alternates, and _then_ iterate and repack. But it
is simpler and more obvious in the case of repo.or.cz to do all in one
iteration, because we can order the repository names easily so that
forkees come first, _and_ we have an easy way to find out what are the
forks of a project.
Ciao,
Dscho
^ permalink raw reply
* Re: [RFC] git-gui USer's Survey 2007 (was: If you would write git from scratch now, what would you change?)
From: Johannes Schindelin @ 2007-11-29 12:01 UTC (permalink / raw)
To: Jan Hudec; +Cc: Jakub Narebski, Shawn O. Pearce, git
In-Reply-To: <20071129065706.GA24070@efreet.light.src>
Hi,
On Thu, 29 Nov 2007, Jan Hudec wrote:
> On Wed, Nov 28, 2007 at 23:48:12 +0000, Johannes Schindelin wrote:
>
> > Furthermore, my complaint was not about a platform where neither C#
> > nor Python work. That is irrelevant. If you have one platform where
> > only one works, and another platform where only the other works, you
> > cannot have a single program for both platforms. Right?
>
> Right.
>
> I probably shouldn't be surprised that mono does not work on older unices,
> but I am a bit surprised python does not.
*Sigh* I managed again to make myself misunderstood.
Even if newer Python does not easily compile on that IRIX, I have an old
Python there (2.2). But I don't have any Python on MSys. (Yes, there is
a _MinGW_ port, but no _MSys_ one.) So for me, Python is out.
Hth,
Dscho
^ permalink raw reply
* [PATCH] Highlight keyboard shortcuts in git-add--interactive
From: Wincent Colaiuta @ 2007-11-29 12:00 UTC (permalink / raw)
To: git; +Cc: gitster, dzwell, peff, Matthieu.Moy, Wincent Colaiuta
In-Reply-To: <7vmysx2ac8.fsf@gitster.siamese.dyndns.org>
The user interface provided by the command loop in git-add--interactive
gives the impression that subcommands can only be launched by entering
an integer identifier from 1 through 8.
A "hidden" feature is that any string can be entered, and an anchored
regex search is used to find the first matching option.
This patch makes this feature a little more obvious by highlighting the
first character of each subcommand (for example "patch" is displayed as
"[p]atch").
A new function is added to detect the shortest unique prefix and this
is used to decide what to highlight. Highlighting is also applied when
choosing files.
In the case where the common prefix may be unreasonably large
highlighting is omitted; in this patch the soft limit (above which the
highlighting will be omitted for a particular item) is 0 (in other words,
there is no soft limit) and the hard limit (above which highlighting will
be omitted for all items) is 3, but this can be tweaked.
The actual highlighting is done by the highlight_prefix function, which
will enable us to implement ANSI color code-based highlighting (most
likely using underline or boldface) in the future.
Signed-off-by: Wincent Colaiuta <win@wincent.com>
---
git-add--interactive.perl | 87 ++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 82 insertions(+), 5 deletions(-)
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index fb1e92a..6e5781b 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -44,7 +44,6 @@ my $status_fmt = '%12s %12s %s';
my $status_head = sprintf($status_fmt, 'staged', 'unstaged', 'path');
# Returns list of hashes, contents of each of which are:
-# PRINT: print message
# VALUE: pathname
# BINARY: is a binary path
# INDEX: is index different from HEAD?
@@ -122,8 +121,6 @@ sub list_modified {
}
push @return, +{
VALUE => $_,
- PRINT => (sprintf $status_fmt,
- $it->{INDEX}, $it->{FILE}, $_),
%$it,
};
}
@@ -159,10 +156,82 @@ sub find_unique {
return $found;
}
+# inserts string into trie and updates count for each character
+sub update_trie {
+ my ($trie, $string) = @_;
+ foreach (split //, $string) {
+ $trie = $trie->{$_} ||= {COUNT => 0};
+ $trie->{COUNT}++;
+ }
+}
+
+# returns an array of tuples (prefix, remainder)
+sub find_unique_prefixes {
+ my @stuff = @_;
+ my @return = ();
+
+ # any single prefix exceeding the soft limit is omitted
+ # if any prefix exceeds the hard limit all are omitted
+ # 0 indicates no limit
+ my $soft_limit = 0;
+ my $hard_limit = 3;
+
+ # build a trie modelling all possible options
+ my %trie;
+ foreach my $print (@stuff) {
+ if ((ref $print) eq 'ARRAY') {
+ $print = $print->[0];
+ }
+ else {
+ $print = $print->{VALUE};
+ }
+ update_trie(\%trie, $print);
+ push @return, $print;
+ }
+
+ # use the trie to find the unique prefixes
+ for (my $i = 0; $i < @return; $i++) {
+ my $ret = $return[$i];
+ my @letters = split //, $ret;
+ my %search = %trie;
+ my ($prefix, $remainder);
+ my $j;
+ for ($j = 0; $j < @letters; $j++) {
+ my $letter = $letters[$j];
+ if ($search{$letter}{COUNT} == 1) {
+ $prefix = substr $ret, 0, $j + 1;
+ $remainder = substr $ret, $j + 1;
+ last;
+ }
+ else {
+ my $prefix = substr $ret, 0, $j;
+ return ()
+ if ($hard_limit && $j + 1 > $hard_limit);
+ }
+ %search = %{$search{$letter}};
+ }
+ if ($soft_limit && $j + 1 > $soft_limit) {
+ $prefix = undef;
+ $remainder = $ret;
+ }
+ $return[$i] = [$prefix, $remainder];
+ }
+ return @return;
+}
+
+# given a prefix/remainder tuple return a string with the prefix highlighted
+# for now use square brackets; later might use ANSI colors (underline, bold)
+sub highlight_prefix {
+ my $prefix = shift;
+ my $remainder = shift;
+ $prefix ? "[$prefix]$remainder" : $remainder;
+}
+
sub list_and_choose {
my ($opts, @stuff) = @_;
my (@chosen, @return);
my $i;
+ my @prefixes = find_unique_prefixes(@stuff) unless $opts->{LIST_ONLY};
TOPLOOP:
while (1) {
@@ -179,10 +248,18 @@ sub list_and_choose {
my $print = $stuff[$i];
if (ref $print) {
if ((ref $print) eq 'ARRAY') {
- $print = $print->[0];
+ $print = @prefixes ?
+ highlight_prefix(@{$prefixes[$i]}) :
+ $print->[0];
}
else {
- $print = $print->{PRINT};
+ my $value = @prefixes ?
+ highlight_prefix(@{$prefixes[$i]}) :
+ $print->{VALUE};
+ $print = sprintf($status_fmt,
+ $print->{INDEX},
+ $print->{FILE},
+ $value);
}
}
printf("%s%2d: %s", $chosen, $i+1, $print);
--
1.5.3.6.953.gdffc
^ permalink raw reply related
* [PATCH v2] Do check_repository_format() early
From: Nguyễn Thái Ngọc Duy @ 2007-11-29 12:21 UTC (permalink / raw)
To: git, Johannes Schindelin, Junio C Hamano
Repository version check is only performed when
setup_git_directory() is called. This makes sure
setup_git_directory_gently() does the check too.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Acked-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
---
Comment updated.
setup.c | 13 ++++++++++---
1 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/setup.c b/setup.c
index faf4137..8fde2b2 100644
--- a/setup.c
+++ b/setup.c
@@ -246,8 +246,14 @@ const char *setup_git_directory_gently(int *nongit_ok)
static char buffer[1024 + 1];
const char *retval;
- if (!work_tree_env)
- return set_work_tree(gitdirenv);
+ if (!work_tree_env) {
+ retval = set_work_tree(gitdirenv);
+ /* config may override worktree
+ * see set_work_tree comment */
+ check_repository_format();
+ return retval;
+ }
+ check_repository_format();
retval = get_relative_cwd(buffer, sizeof(buffer) - 1,
get_git_work_tree());
if (!retval || !*retval)
@@ -287,6 +293,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
if (!work_tree_env)
inside_work_tree = 0;
setenv(GIT_DIR_ENVIRONMENT, ".", 1);
+ check_repository_format();
return NULL;
}
chdir("..");
@@ -307,6 +314,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
if (!work_tree_env)
inside_work_tree = 1;
git_work_tree_cfg = xstrndup(cwd, offset);
+ check_repository_format();
if (offset == len)
return NULL;
@@ -367,7 +375,6 @@ int check_repository_format(void)
const char *setup_git_directory(void)
{
const char *retval = setup_git_directory_gently(NULL);
- check_repository_format();
/* If the work tree is not the default one, recompute prefix */
if (inside_work_tree < 0) {
--
1.5.3.6.2041.g106f-dirty
^ permalink raw reply related
* Re: git guidance
From: Kyle Moffett @ 2007-11-29 12:57 UTC (permalink / raw)
To: Al Boldi; +Cc: linux-kernel, git
In-Reply-To: <200711290827.04950.a1426z@gawab.com>
On Nov 29, 2007, at 00:27:04, Al Boldi wrote:
> Jakub Narebski wrote:
>> Besides, you can always use "git show <revision>:<file>". For
>> example gitweb (and I think other web interfaces) can show any
>> version of a file or a directory, accessing only repository.
>
> Sure, browsing is the easy part, but Version Control starts when
> things become writable.
But... git history is very inherently completely immutable once
created... that's the only way you can index everything with a simple
SHA-1. If you want to write to the "git filesystem" by adding new
commits then you need to use the appropriate commands, same as every
other VCS on the planet.
Cheers,
Kyle Moffett
^ permalink raw reply
* Re: Cover grafting in the Git User's Manual
From: Markus Armbruster @ 2007-11-29 13:20 UTC (permalink / raw)
To: Peter Baumann; +Cc: git
In-Reply-To: <20071128184228.GB4461@xp.machine.xx>
Peter Baumann <waste.manager@gmx.de> writes:
> On Wed, Nov 28, 2007 at 07:23:01PM +0100, Markus Armbruster wrote:
>> The only mention of grafting in the manual is in the glossary:
>>
>> Grafts enables two otherwise different lines of development to
>> be joined together by recording fake ancestry information for
>> commits. This way you can make git pretend the set of parents
>> a commit has is different from what was recorded when the
>> commit was created. Configured via the .git/info/grafts file.
>>
>> I believe it would be useful to cover this better, perhaps in chapter
>> 5. Rewriting history and maintaining patch series. It certainly would
>> have saved me a few hours of digging. I already understood enough of
>> git to *know* that what I wanted must be possible (supply missing
>> parents of merges in a repository imported with parsecvs), but I
>> didn't know the magic keyword was graft. I managed to figure it out
>> >from the glossary, git-filter-branch(1) and GitWiki's GraftPoint page.
>>
>> I'm neither writer nor git expert, but here's my try anyway:
>>
>> Rewriting ancestry with grafts
>>
>> Grafts enables two otherwise different lines of development to be
>> joined together by recording fake ancestry information for commits.
>> This way you can make git pretend the set of parents a commit has is
>> different from what was recorded when the commit was created.
>>
>> Why would you want to do that? Say, you imported a repository from an
>> SCM that doesn't record merges properly, e.g. CVS. Grafts let you add
>> the missing parents to the merge commits. Or you switched your
>> project to git by populating a new repository with current sources,
>> and later decide you want more history. Committing old versions is
>> easy enough, but you also need to graft a parent to your original root
>> commit.
>>
>> Graft points are configured via the .git/info/grafts file. It has one
>> record per line describing a commit and its fake parents by listing
>> object names separated by a space and terminated by a newline.
>>
>> <commit sha1> <parent sha1> [<parent sha1>]*
>>
>> A graft point does not actually change its commit. Nothing can. What
>> can be done is rewriting the commit and its descendants.
>> git-filter-branch does that:
>>
>> $ cat .git/info/grafts
>> db5a561750ae87615719ae409d1f50c9dfc3fa71 08f2fa81d104b937c1f24c68f56e9d5039356764 8c231303bb995cbfdfd1c434a59a7c96ea2f0251
>> git-filter-branch HEAD ^08f2fa81d104b937c1f24c68f56e9d5039356764 ^8c231303bb995cbfdfd1c434a59a7c96ea2f0251
>>
>> This rewrites history between head and the graft-point to include the
>> grafted parents.
>
> Did I overlook something or isn't
>
> git-filter-branch HEAD ^db5a561750ae87615719ae409d1f50c9dfc3fa71
>
> what you are looking for? Only db5a56 could get rewritten and obviously
> all the commits having it as a parent.
>
> -Peter
That rewrites all commits reachable from HEAD that are not reachable
from db5a56. In particular, it doesn't rewrite db5a56, does it?
^ permalink raw reply
* Re: [PATCH] Move all dashed form git commands to libexecdir
From: Nicolas Pitre @ 2007-11-29 14:09 UTC (permalink / raw)
To: Nguyen Thai Ngoc Duy; +Cc: Junio C Hamano, Jan Hudec, Johannes Schindelin, git
In-Reply-To: <fcaeb9bf0711281917p56cc4228m6c401286439e2a34@mail.gmail.com>
On Thu, 29 Nov 2007, Nguyen Thai Ngoc Duy wrote:
> On Nov 29, 2007 6:14 AM, Junio C Hamano <gitster@pobox.com> wrote:
> >
> > "Nguyen Thai Ngoc Duy" <pclouds@gmail.com> writes:
> >
> > > On Nov 28, 2007 8:13 AM, Junio C Hamano <gitster@pobox.com> wrote:
> > >> In case somebody is thinking about 36e5e70e0f40 (Start deprecating
> > >> "git-command" in favor of "git command"), that is a somewhat different
> > >> issue. What Linus suggested is not installing git-foo link for built-in
> > >> commands _anywhere_ on the filesystem. Not just "out of user's PATH".
> > >> That is not deprecating dash form but removing the support for it. We
> > >> need to give ample time for users to adjust to such a change.
> > >
> > > A little note on this one. I've been using git without builtin links
> > > for a while with my git-box port. There are still some builtin fixups
> > > needed. And because execv_git_cmd() always uses dash form, so it's
> > > impossible to use vanilla git without builtin links.
> >
> > Thanks for a heads up.
> >
> > Would people agree with a rough roadmap like this?
> >
> > - v1.5.4 will ship with gitexecdir=$(bindir) in Makefile. But the
> > release notes for the version will warn users that:
> >
> > (1) using git-foo from the command line, and
> >
> > (2) using git-foo from your scripts without first prepending the
> > return value of "git --exec-path" to the PATH
> >
> > is now officially deprecated (it has been deprecated for a long time
> > since January 2006, v1.2.0~149) and upcoming v1.5.5 will ship with
> > the default configuration that does not install git-foo form in
> > user's PATH.
> >
> > - Post v1.5.4, start cooking gitexecdir=$(libexecdir)/git-core, aiming
> > for inclusion in v1.5.5, perhaps in Mar-Feb 2008 timeframe.
> >
> > - The release notes for v1.5.5 will warn users that git-foo will be
> > removed in v1.6.0 for many commands and it will be merely an accident
> > if some of them still work.
> >
> > - Post v1.5.5, start cooking the change that does not install hardlinks
> > for built-in commands, aiming for inclusion in v1.6.0, by the end of
> > 2008.
>
> There won't be a stage when only porcelain git-foos are in $(bindir)?
> I could stop working on the relevant patch then.
Well, I personally found your effort really nice. I think Junio is
overly cautious in this case, and I would prefer to see the number of
git commands in the default path drop rather sooner than later.
Nicolas
^ permalink raw reply
* Re: [RFC] use typechange as rename source
From: Jeff King @ 2007-11-29 14:14 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vir3l2a1i.fsf@gitster.siamese.dyndns.org>
On Wed, Nov 28, 2007 at 04:02:49PM -0800, Junio C Hamano wrote:
> I do not think this is a risky change; it won't add too many rename
> sources we did not consider traditionally (typechanges are usually rare
> event anyway).
OK. What next? Did the patch I sent make sense? Do you want a cleaned up
version with a commit message and signoff, or does it need work?
> You are copying the source to elsewhere and then completely rewriting it
> (even making it into a different type), so I do not think 'copied' is so
> unreasonable. An alternative would be to say you renamed it and then
> created something totally different, which would also be reasonable.
I am inclined to leave it as 'copied' for now because it makes some
sense and is the least invasive change (and is independent of adding the
rename source, so we can always change it later).
-Peff
^ permalink raw reply
* Re: [PATCH 3/3] cvsimport: miscellaneous packed-ref fixes
From: Jeff King @ 2007-11-29 14:19 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Emanuele Giaquinta, git
In-Reply-To: <7vsl2pzxdf.fsf@gitster.siamese.dyndns.org>
On Wed, Nov 28, 2007 at 04:52:28PM -0800, Junio C Hamano wrote:
> > @@ -998,7 +996,7 @@ if ($orig_branch) {
> > $orig_branch = "master";
> > print "DONE; creating $orig_branch branch\n" if $opt_v;
> > system("git-update-ref", "refs/heads/master", "$remote/$opt_o")
> > - unless -f "$git_dir/refs/heads/master";
> > + defined get_headref('refs/heads/master');
>
> Where did the unless go ;-)?
Bah, I even ran this through the test suite, but obviously forgot a
'make' in the middle.
> Thanks, queued.
Thanks. Sorry for all the mistakes; I think I made more work in catching
my errors than went into the original patch series. ;)
-Peff
^ permalink raw reply
* [PATCH] Add "--expire <time>" option to 'git prune'
From: Johannes Schindelin @ 2007-11-29 14:21 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Johannes Sixt, git, pasky
In-Reply-To: <Pine.LNX.4.64.0711291146090.27959@racer.site>
Earlier, 'git prune' would prune all loose unreachable objects.
This could be quite dangerous, as the objects could be used in
an ongoing operation.
This patch adds a mode to expire only loose, unreachable objects
which are older than a certain time. For example, by
git prune --expire 14.days
you can prune only those objects which are loose, unreachable
and older than 14 days (and thus probably outdated).
The implementation uses st.st_mtime rather than st.st_ctime,
because it can be tested better, using 'touch -d <time>' (and
omitting the test when the platform does not support that
command line switch).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
On Thu, 29 Nov 2007, Johannes Schindelin wrote:
> Note that "prune" is not (yet) an option [for repo.or.cz], since
> it could possibly destroy objects which are needed in an ongoing
> push operation.
>
> However, we could do exactly the same as with reflogs: introduce
> a grace period (with loose objects, we can use the ctime...)
and this patch does that (except using mtime as ctime, for reasons
explained in the commit message.
Obviously, this patch is asking for a cousin, changing
git-gc to use this option, and maybe introduce a config
variable gc.pruneAge.
Documentation/git-prune.txt | 5 ++++-
builtin-prune.c | 21 ++++++++++++++++++++-
t/t1410-reflog.sh | 18 ++++++++++++++++++
3 files changed, 42 insertions(+), 2 deletions(-)
diff --git a/Documentation/git-prune.txt b/Documentation/git-prune.txt
index 0ace233..9835bdb 100644
--- a/Documentation/git-prune.txt
+++ b/Documentation/git-prune.txt
@@ -8,7 +8,7 @@ git-prune - Prune all unreachable objects from the object database
SYNOPSIS
--------
-'git-prune' [-n] [--] [<head>...]
+'git-prune' [-n] [--expire <expire>] [--] [<head>...]
DESCRIPTION
-----------
@@ -31,6 +31,9 @@ OPTIONS
\--::
Do not interpret any more arguments as options.
+\--expire <time>::
+ Only expire loose objects older than <time>.
+
<head>...::
In addition to objects
reachable from any of our references, keep objects
diff --git a/builtin-prune.c b/builtin-prune.c
index 44df59e..b5e7684 100644
--- a/builtin-prune.c
+++ b/builtin-prune.c
@@ -7,15 +7,24 @@
static const char prune_usage[] = "git-prune [-n]";
static int show_only;
+static unsigned long expire;
static int prune_object(char *path, const char *filename, const unsigned char *sha1)
{
+ const char *fullpath = mkpath("%s/%s", path, filename);
+ if (expire) {
+ struct stat st;
+ if (lstat(fullpath, &st))
+ return error("Could not stat '%s'", fullpath);
+ if (st.st_mtime > expire)
+ return 0;
+ }
if (show_only) {
enum object_type type = sha1_object_info(sha1, NULL);
printf("%s %s\n", sha1_to_hex(sha1),
(type > 0) ? typename(type) : "unknown");
} else
- unlink(mkpath("%s/%s", path, filename));
+ unlink(fullpath);
return 0;
}
@@ -85,6 +94,16 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
show_only = 1;
continue;
}
+ if (!strcmp(arg, "--expire")) {
+ if (++i < argc) {
+ expire = approxidate(argv[i]);
+ continue;
+ }
+ }
+ else if (!prefixcmp(arg, "--expire=")) {
+ expire = approxidate(arg + 9);
+ continue;
+ }
usage(prune_usage);
}
diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh
index 12a53ed..f093802 100755
--- a/t/t1410-reflog.sh
+++ b/t/t1410-reflog.sh
@@ -201,4 +201,22 @@ test_expect_success 'delete' '
! grep dragon < output
'
+test_expect_success 'prune --expire' '
+
+ BLOB=$(echo aleph | git hash-object -w --stdin) &&
+ BLOB_FILE=.git/objects/$(echo $BLOB | sed "s/^../&\//") &&
+ test 20 = $(git count-objects | sed "s/ .*//") &&
+ test -f $BLOB_FILE &&
+ git reset --hard &&
+ if touch -d "Jan 1 1970" $BLOB_FILE
+ then
+ git prune --expire 1.day &&
+ test 19 = $(git count-objects | sed "s/ .*//") &&
+ ! test -f $BLOB_FILE
+ else
+ say "Skipping test due to non-working touch -d"
+ fi
+
+'
+
test_done
--
1.5.3.6.2087.g788ea4
^ permalink raw reply related
* Re: [PATCH] Add "--expire <time>" option to 'git prune'
From: Johannes Sixt @ 2007-11-29 14:35 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Junio C Hamano, git, pasky
In-Reply-To: <Pine.LNX.4.64.0711291419350.27959@racer.site>
Johannes Schindelin schrieb:
> +test_expect_success 'prune --expire' '
> +
> + BLOB=$(echo aleph | git hash-object -w --stdin) &&
> + BLOB_FILE=.git/objects/$(echo $BLOB | sed "s/^../&\//") &&
> + test 20 = $(git count-objects | sed "s/ .*//") &&
> + test -f $BLOB_FILE &&
> + git reset --hard &&
Here you could throw in:
git prune --expire=1.hour.ago &&
test 20 = $(git count-objects | sed "s/ .*//") &&
test -f $BLOB_FILE &&
to test that the object is not pruned (and the alternate --expire syntax).
> + if touch -d "Jan 1 1970" $BLOB_FILE
> + then
> + git prune --expire 1.day &&
> + test 19 = $(git count-objects | sed "s/ .*//") &&
> + ! test -f $BLOB_FILE
> + else
> + say "Skipping test due to non-working touch -d"
> + fi
-- Hannes
^ permalink raw reply
* Re: [PATCH] Highlight keyboard shortcuts in git-add--interactive
From: Jeff King @ 2007-11-29 14:51 UTC (permalink / raw)
To: Wincent Colaiuta; +Cc: git, gitster, dzwell, Matthieu.Moy
In-Reply-To: <1196337638-45972-1-git-send-email-win@wincent.com>
On Thu, Nov 29, 2007 at 01:00:38PM +0100, Wincent Colaiuta wrote:
> A new function is added to detect the shortest unique prefix and this
> is used to decide what to highlight. Highlighting is also applied when
> choosing files.
I think this is very nicely implemented.
Acked-by: Jeff King <peff@peff.net>
> +# returns an array of tuples (prefix, remainder)
> +sub find_unique_prefixes {
> + my @stuff = @_;
I know we generally use this more C-ish argument convention to document
"here are the arguments to this function", but it does actually make a
copy of the @_ array (and using @_ implies a potentially large number of
arguments).
It probably doesn't matter here, though, since add--interactive is not
performance critical, and you probably can't have more than a few dozen
entries before it becomes unreadable anyway.
-Peff
^ permalink raw reply
* Re: [PATCH] Move all dashed form git commands to libexecdir
From: Jeff King @ 2007-11-29 15:08 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Nguyen Thai Ngoc Duy, Jan Hudec, Johannes Schindelin, git
In-Reply-To: <7vfxyq2c9b.fsf@gitster.siamese.dyndns.org>
On Wed, Nov 28, 2007 at 03:14:56PM -0800, Junio C Hamano wrote:
> - Post v1.5.5, start cooking the change that does not install hardlinks
> for built-in commands, aiming for inclusion in v1.6.0, by the end of
> 2008.
I am against this, unless it is configurable. I think the goal of
reducing user-visible commands is fine, and moving things to
$(libexecdir) is a good way of doing that.
However, I personally still think the 'git-foo' forms are valuable
(because fingers have already been trained, and because
non-bash-programmable completions understand them). And I don't mind
putting $(libexecdir)/git-core in my PATH to retain this behavior; it's
a one-time configuration tweak, and it helps new users with the
overwhelming command set.
But I don't see a point to removing the links entirely. The annoyance
factor for people who want git-* is much higher, and I don't see that it
actually buys us any help for new users (who will no longer care after
everything is hidden in $(libexecdir) anyway).
-Peff
^ permalink raw reply
* Re: [PATCH] Add "--expire <time>" option to 'git prune'
From: Jeff King @ 2007-11-29 15:12 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Junio C Hamano, Johannes Sixt, git, pasky
In-Reply-To: <Pine.LNX.4.64.0711291419350.27959@racer.site>
On Thu, Nov 29, 2007 at 02:21:23PM +0000, Johannes Schindelin wrote:
> This patch adds a mode to expire only loose, unreachable objects
> which are older than a certain time. For example, by
>
> git prune --expire 14.days
>
> you can prune only those objects which are loose, unreachable
> and older than 14 days (and thus probably outdated).
Does this now make git-prune safe for automatic running?
I suppose you could still be actively manipulating refs that point to
very old objects.
-Peff
^ permalink raw reply
* [PATCH v2] Add "--expire <time>" option to 'git prune'
From: Johannes Schindelin @ 2007-11-29 15:22 UTC (permalink / raw)
To: Johannes Sixt; +Cc: Junio C Hamano, git, pasky
In-Reply-To: <474ECE2A.9050700@viscovery.net>
Earlier, 'git prune' would prune all loose unreachable objects.
This could be quite dangerous, as the objects could be used in
an ongoing operation.
This patch adds a mode to expire only loose, unreachable objects
which are older than a certain time. For example, by
git prune --expire 14.days
you can prune only those objects which are loose, unreachable
and older than 14 days (and thus probably outdated).
The implementation uses st.st_mtime rather than st.st_ctime,
because it can be tested better, using 'touch -d <time>' (and
omitting the test when the platform does not support that
command line switch).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
On Thu, 29 Nov 2007, Johannes Sixt wrote:
> Johannes Schindelin schrieb:
> > +test_expect_success 'prune --expire' '
> > +
> > + BLOB=$(echo aleph | git hash-object -w --stdin) &&
> > + BLOB_FILE=.git/objects/$(echo $BLOB | sed "s/^../&\//") &&
> > + test 20 = $(git count-objects | sed "s/ .*//") &&
> > + test -f $BLOB_FILE &&
> > + git reset --hard &&
>
> Here you could throw in:
>
> git prune --expire=1.hour.ago &&
> test 20 = $(git count-objects | sed "s/ .*//") &&
> test -f $BLOB_FILE &&
>
> to test that the object is not pruned (and the alternate
> --expire syntax).
Good idea!
Documentation/git-prune.txt | 5 ++++-
builtin-prune.c | 21 ++++++++++++++++++++-
t/t1410-reflog.sh | 21 +++++++++++++++++++++
3 files changed, 45 insertions(+), 2 deletions(-)
diff --git a/Documentation/git-prune.txt b/Documentation/git-prune.txt
index 0ace233..9835bdb 100644
--- a/Documentation/git-prune.txt
+++ b/Documentation/git-prune.txt
@@ -8,7 +8,7 @@ git-prune - Prune all unreachable objects from the object database
SYNOPSIS
--------
-'git-prune' [-n] [--] [<head>...]
+'git-prune' [-n] [--expire <expire>] [--] [<head>...]
DESCRIPTION
-----------
@@ -31,6 +31,9 @@ OPTIONS
\--::
Do not interpret any more arguments as options.
+\--expire <time>::
+ Only expire loose objects older than <time>.
+
<head>...::
In addition to objects
reachable from any of our references, keep objects
diff --git a/builtin-prune.c b/builtin-prune.c
index 44df59e..b5e7684 100644
--- a/builtin-prune.c
+++ b/builtin-prune.c
@@ -7,15 +7,24 @@
static const char prune_usage[] = "git-prune [-n]";
static int show_only;
+static unsigned long expire;
static int prune_object(char *path, const char *filename, const unsigned char *sha1)
{
+ const char *fullpath = mkpath("%s/%s", path, filename);
+ if (expire) {
+ struct stat st;
+ if (lstat(fullpath, &st))
+ return error("Could not stat '%s'", fullpath);
+ if (st.st_mtime > expire)
+ return 0;
+ }
if (show_only) {
enum object_type type = sha1_object_info(sha1, NULL);
printf("%s %s\n", sha1_to_hex(sha1),
(type > 0) ? typename(type) : "unknown");
} else
- unlink(mkpath("%s/%s", path, filename));
+ unlink(fullpath);
return 0;
}
@@ -85,6 +94,16 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
show_only = 1;
continue;
}
+ if (!strcmp(arg, "--expire")) {
+ if (++i < argc) {
+ expire = approxidate(argv[i]);
+ continue;
+ }
+ }
+ else if (!prefixcmp(arg, "--expire=")) {
+ expire = approxidate(arg + 9);
+ continue;
+ }
usage(prune_usage);
}
diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh
index 12a53ed..3924dc4 100755
--- a/t/t1410-reflog.sh
+++ b/t/t1410-reflog.sh
@@ -201,4 +201,25 @@ test_expect_success 'delete' '
! grep dragon < output
'
+test_expect_success 'prune --expire' '
+
+ BLOB=$(echo aleph | git hash-object -w --stdin) &&
+ BLOB_FILE=.git/objects/$(echo $BLOB | sed "s/^../&\//") &&
+ test 20 = $(git count-objects | sed "s/ .*//") &&
+ test -f $BLOB_FILE &&
+ git reset --hard &&
+ git prune --expire=1.hour.ago &&
+ test 20 = $(git count-objects | sed "s/ .*//") &&
+ test -f $BLOB_FILE &&
+ if touch -d "Jan 1 1970" $BLOB_FILE
+ then
+ git prune --expire 1.day &&
+ test 19 = $(git count-objects | sed "s/ .*//") &&
+ ! test -f $BLOB_FILE
+ else
+ say "Skipping test due to non-working touch -d"
+ fi
+
+'
+
test_done
--
1.5.3.6.2088.g8c260
^ permalink raw reply related
* Re: git guidance
From: Jing Xue @ 2007-11-29 15:52 UTC (permalink / raw)
To: Al Boldi; +Cc: linux-kernel, git
Quoting Al Boldi <a1426z@gawab.com>:
> Sure, browsing is the easy part, but Version Control starts when things
> become writable.
But how is that supposed to work? What happens when you make some
changes to a file and save it? Do you want the "git file system" to
commit it right aways or wait until you to issue a "commit" command?
The first behavior would obviously be wrong, and the second would make
the "file system" not operationally transparent anyways. Right?
By the way, the only SCM I have worked with that tries to mount its
repository (or a view on top of it) as a file system is ClearCase with
its dynamic views. And, between the buggy file system implementation,
the intrusion on workflow, and the lack of scalability, at least in
the organization I worked for, it turned out to be a horrible,
horrible, horrible idea.
Cheers.
--
Jing Xue
^ permalink raw reply
* Re: [PATCH] Add "--expire <time>" option to 'git prune'
From: Johannes Schindelin @ 2007-11-29 16:13 UTC (permalink / raw)
To: Jeff King; +Cc: Junio C Hamano, Johannes Sixt, git, pasky
In-Reply-To: <20071129151211.GB32296@coredump.intra.peff.net>
Hi,
On Thu, 29 Nov 2007, Jeff King wrote:
> On Thu, Nov 29, 2007 at 02:21:23PM +0000, Johannes Schindelin wrote:
>
> > This patch adds a mode to expire only loose, unreachable objects
> > which are older than a certain time. For example, by
> >
> > git prune --expire 14.days
> >
> > you can prune only those objects which are loose, unreachable
> > and older than 14 days (and thus probably outdated).
>
> Does this now make git-prune safe for automatic running?
>
> I suppose you could still be actively manipulating refs that point to
> very old objects.
That's why I want to have it configurable from git-gc.
Ciao,
Dscho
^ permalink raw reply
* Re: git-svn rebase issues (the commiter gets changed)
From: Kelvie Wong @ 2007-11-29 16:16 UTC (permalink / raw)
To: Eric Wong; +Cc: git
In-Reply-To: <20071129075205.GB32277@soma>
On Nov 28, 2007 11:52 PM, Eric Wong <normalperson@yhbt.net> wrote:
> Kelvie Wong <kelvie@ieee.org> wrote:
> > When using git-svn rebase (I'm not sure if this happens with a regular
> > rebase as well, I use use git-svn primarily at work), the following
> > oddity happens:
> >
> > kelvie@mudd (working) qt $ git-cat-file commit
> > c27e6207c9078d4225288d55454d6577f0135c16
> > tree 13d9ef9cc67f5e6381d7697e5794c0ab5f72c729
> > parent b9eb187d3029c5f9a816cb8f5473d9b239952d53
> > author kwong <kwong@e2d93294-a71b-0410-9dca-e2ea525a67c9> 1195596864 +0000
> > committer cscrimgeour
> > <cscrimgeour@e2d93294-a71b-0410-9dca-e2ea525a67c9> 1195691944 +0000
>
> This is strange. Does this commit end below? or did you truncate
> the git-svn-id: line from this message?
>
This is one of my local commits, not yet commited to the SVN repo.
I've talked on IRC, and it seems I'm not the only one that has this
problem. I have heard that the committer timestamp of _all_ rebased
local commits gets changed to the last SVN commit (made by someone
else), but the committer doesn't get changed (except in the first
commit rebased after SVN).
> >
> > Qt/FME Extensions: QFMEDialog/QFMEWizard -> Windows only, for now
> >
> > This is also a reapplication of r39657, which got rolled back.
> >
> > These have dependencies on QWinWidget (which is a part of the MFC/Qt Migration
> > Solution), and thus, it does not build without it.
> > <kw>
> > kelvie@mudd (working) qt $ git-cat-file commit
> > 7075991c67c6d409ec2315dfeef6f45dd328485b
> > tree 13d9ef9cc67f5e6381d7697e5794c0ab5f72c729
> > parent b9eb187d3029c5f9a816cb8f5473d9b239952d53
> > author kwong <kwong@e2d93294-a71b-0410-9dca-e2ea525a67c9> 1195596864 +0000
> > committer Kelvie Wong <Kelvie.Wong@safe.com> 1195747291 +0000
>
> This commit hasn't made it into SVN, yet, right? If so, then that's
> alright.
>
> >
> > Qt/FME Extensions: QFMEDialog/QFMEWizard -> Windows only, for now
> >
> > This is also a reapplication of r39657, which got rolled back.
> >
> > These have dependencies on QWinWidget (which is a part of the MFC/Qt Migration
> > Solution), and thus, it does not build without it.
> > <kw>
> >
> >
> > These are both the exact same commit (the tree, parent, and author are
> > equivalent).
> >
> > Sometimes (not always), the committer in a commit changes to be the
> > committer of the parent (svn) commit. This only happens to the
> > commits whose parent is the SVN commit. In the above example,
> > cscrimgeour is a SVN user, who obviously could not have changed my
> > code; the proper commit is the one at the bottom.
> >
> > Both of these are the first local commit that I have rebased onto SVN.
>
> Did you get these commits by cherry-picking (or format-patch + am)
> from another SVN branch? Have these commits been made to SVN already?
>
It's a commit I made directly.
> `gitk --reflog --all' may reveal some answers or clarify
> things for you (assuming you have reflogs enabled in .git/config).
>
> Rebase (all forms of it) *does* rewrite committer info, but how you got
> cscrimgeour in there is very strange to me.
>
> --
> Eric Wong
>
Just did it again this morning, with a clean test branch:
kelvie@mudd (text-edit) qt $ git checkout -b test git-svn
Switched to a new branch "test"
kelvie@mudd (test) qt $ touch test
kelvie@mudd (test) qt $ git add test
kelvie@mudd (test) qt $ git commit -a -m 'Test!'
Created commit 05c4016: Test!
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 apps/qt/test
kelvie@mudd (test) qt $ git-cat-file commit HEAD
tree 867c0aa4c814542f0752b5d4c85fc96ba2279aac
parent 831ffbf25057ed30274d4216269c572cfce12184
author Kelvie Wong <Kelvie.Wong@safe.com> 1196352603 -0800
committer Kelvie Wong <Kelvie.Wong@safe.com> 1196352603 -0800
Test!
kelvie@mudd (test) qt $ git svn rebase
<snip>
HEAD is now at 7319c2a... (svn commit message)
kelvie@mudd (test) qt $ git-cat-file commit HEAD
tree 4edacbd41af76ac243099467b33350887c0fb03d
parent 7319c2a810554aab25a688bcc2b16fc60529b59d
author Kelvie Wong <Kelvie.Wong@safe.com> 1196352603 -0800
committer ogibbins <ogibbins@e2d93294-a71b-0410-9dca-e2ea525a67c9>
1196346907 +0000
Test!
kelvie@mudd (test) qt $ git --version
git version 1.5.3.6.736.gb7f30
And again, the committer of a local commit gets changed.
Now, this part is more interesting:
kelvie@mudd (test) qt $ git checkout working
Switched to branch "working"
kelvie@mudd (working) qt $ git svn rebase
<no fetch, just a checkout and rebase>
And when I cat-file the commit, this time it's preserved. Wild guess
here (this behaviour seems kind of inconsistent), but it has to do
with the transition between fetch and rebase? Or is this a bug in
git-rebase somewhere?
--
Kelvie Wong
^ permalink raw reply
* Re: git guidance
From: Linus Torvalds @ 2007-11-29 16:19 UTC (permalink / raw)
To: Jing Xue; +Cc: Al Boldi, linux-kernel, git
In-Reply-To: <20071129105220.v40i22q4gw4cgoso@intranet.digizenstudio.com>
On Thu, 29 Nov 2007, Jing Xue wrote:
>
> By the way, the only SCM I have worked with that tries to mount its
> repository (or a view on top of it) as a file system is ClearCase with
> its dynamic views. And, between the buggy file system implementation,
> the intrusion on workflow, and the lack of scalability, at least in
> the organization I worked for, it turned out to be a horrible,
> horrible, horrible idea.
Doing a read-only mount setup tends to be pretty easy, but it's largely
pointless except for specialty uses. Ie it's obviously not useful for
actual *development*, but it can be useful for some other cases.
For example, a read-only revctrl filesystem can be a _very_ useful thing
for test-farms, where you may have hundreds of clients that run tests on
possibly different versions at the same time. In situations like that, the
read-only mount can actually often be done as a user-space NFS server on
some machine.
The advantage is that you don't need to export close to infinite amounts
of versions from a "real" filesystem, or make the clients have their own
copies. And if you do it as a user-space NFS server (or samba, for that
matter), it's even portable, unlike many other approaches. The read-only
part also makes 99% of all the complexity go away, and it turns out to be
a fairly easy exercise to do.
So I don't think the filesystem approach is _wrong_ per se. But yes, doing
it read-write is almost invariably a big mistake. On operatign systems
that support a "union mount" approach, it's likely much better to have a
read-only revctl thing, and then over-mount a regular filesystem on top of
it.
Trying to make it read-write from the revctl engine standpoint is almost
certainly totally insane.
Linus
^ permalink raw reply
* problem with git detecting proper renames
From: Kumar Gala @ 2007-11-29 16:57 UTC (permalink / raw)
To: git
I was wondering if there was a way to ensure that git tracks renames
properly (or maybe its reporting them properly).
I did some git-mv and got the following:
the problem is git seems confused about what file was associated with its
source.
For example:
.../mpc8541cds => freescale/mpc8555cds}/init.S
thanks
- k
---
(the following is the results of a git-format-patch after the git-mv)
Makefile | 6 +-
board/cds/mpc8548cds/Makefile | 60 -----
board/cds/mpc8555cds/Makefile | 60 -----
board/cds/mpc8555cds/init.S | 255 --------------------
board/cds/mpc8555cds/u-boot.lds | 150 ------------
board/{cds => freescale}/common/cadmus.c | 0
board/{cds => freescale}/common/cadmus.h | 0
board/{cds => freescale}/common/eeprom.c | 0
board/{cds => freescale}/common/eeprom.h | 0
board/{cds => freescale}/common/ft_board.c | 0
board/{cds => freescale}/common/via.c | 0
board/{cds => freescale}/common/via.h | 0
board/{cds => freescale}/mpc8541cds/Makefile | 0
board/{cds => freescale}/mpc8541cds/config.mk | 0
board/{cds => freescale}/mpc8541cds/init.S | 0
board/{cds => freescale}/mpc8541cds/mpc8541cds.c | 0
board/{cds => freescale}/mpc8541cds/u-boot.lds | 4 +-
.../mpc8541cds => freescale/mpc8548cds}/Makefile | 0
board/{cds => freescale}/mpc8548cds/config.mk | 0
board/{cds => freescale}/mpc8548cds/init.S | 0
board/{cds => freescale}/mpc8548cds/mpc8548cds.c | 0
board/{cds => freescale}/mpc8548cds/u-boot.lds | 4 +-
.../mpc8541cds => freescale/mpc8555cds}/Makefile | 0
board/{cds => freescale}/mpc8555cds/config.mk | 0
.../mpc8541cds => freescale/mpc8555cds}/init.S | 0
board/{cds => freescale}/mpc8555cds/mpc8555cds.c | 0
.../mpc8541cds => freescale/mpc8555cds}/u-boot.lds | 4 +-
27 files changed, 9 insertions(+), 534 deletions(-)
delete mode 100644 board/cds/mpc8548cds/Makefile
delete mode 100644 board/cds/mpc8555cds/Makefile
delete mode 100644 board/cds/mpc8555cds/init.S
delete mode 100644 board/cds/mpc8555cds/u-boot.lds
rename board/{cds => freescale}/common/cadmus.c (100%)
rename board/{cds => freescale}/common/cadmus.h (100%)
rename board/{cds => freescale}/common/eeprom.c (100%)
rename board/{cds => freescale}/common/eeprom.h (100%)
rename board/{cds => freescale}/common/ft_board.c (100%)
rename board/{cds => freescale}/common/via.c (100%)
rename board/{cds => freescale}/common/via.h (100%)
copy board/{cds => freescale}/mpc8541cds/Makefile (100%)
rename board/{cds => freescale}/mpc8541cds/config.mk (100%)
copy board/{cds => freescale}/mpc8541cds/init.S (100%)
rename board/{cds => freescale}/mpc8541cds/mpc8541cds.c (100%)
copy board/{cds => freescale}/mpc8541cds/u-boot.lds (97%)
copy board/{cds/mpc8541cds => freescale/mpc8548cds}/Makefile (100%)
rename board/{cds => freescale}/mpc8548cds/config.mk (100%)
rename board/{cds => freescale}/mpc8548cds/init.S (100%)
rename board/{cds => freescale}/mpc8548cds/mpc8548cds.c (100%)
rename board/{cds => freescale}/mpc8548cds/u-boot.lds (97%)
rename board/{cds/mpc8541cds => freescale/mpc8555cds}/Makefile (100%)
rename board/{cds => freescale}/mpc8555cds/config.mk (100%)
rename board/{cds/mpc8541cds => freescale/mpc8555cds}/init.S (100%)
rename board/{cds => freescale}/mpc8555cds/mpc8555cds.c (100%)
rename board/{cds/mpc8541cds => freescale/mpc8555cds}/u-boot.lds (97%)
diff --git a/Makefile b/Makefile
index 92632b9..a0f35df 100644
--- a/Makefile
+++ b/Makefile
@@ -1945,7 +1945,7 @@ MPC8541CDS_config: unconfig
echo "#define CONFIG_LEGACY" >>$(obj)include/config.h ; \
echo "... legacy" ; \
fi
- @$(MKCONFIG) -a MPC8541CDS ppc mpc85xx mpc8541cds cds
+ @$(MKCONFIG) -a MPC8541CDS ppc mpc85xx mpc8541cds freescale
MPC8544DS_config: unconfig
@$(MKCONFIG) $(@:_config=) ppc mpc85xx mpc8544ds freescale
@@ -1958,7 +1958,7 @@ MPC8548CDS_config: unconfig
echo "#define CONFIG_LEGACY" >>$(obj)include/config.h ; \
echo "... legacy" ; \
fi
- @$(MKCONFIG) -a MPC8548CDS ppc mpc85xx mpc8548cds cds
+ @$(MKCONFIG) -a MPC8548CDS ppc mpc85xx mpc8548cds freescale
MPC8555CDS_legacy_config \
MPC8555CDS_config: unconfig
@@ -1968,7 +1968,7 @@ MPC8555CDS_config: unconfig
echo "#define CONFIG_LEGACY" >>$(obj)include/config.h ; \
echo "... legacy" ; \
fi
- @$(MKCONFIG) -a MPC8555CDS ppc mpc85xx mpc8555cds cds
+ @$(MKCONFIG) -a MPC8555CDS ppc mpc85xx mpc8555cds freescale
MPC8568MDS_config: unconfig
@$(MKCONFIG) $(@:_config=) ppc mpc85xx mpc8568mds freescale
[snip]
diff --git a/board/cds/mpc8541cds/u-boot.lds b/board/freescale/mpc8555cds/u-boot.lds
similarity index 97%
rename from board/cds/mpc8541cds/u-boot.lds
rename to board/freescale/mpc8555cds/u-boot.lds
index 7a5daef..df21ea8 100644
--- a/board/cds/mpc8541cds/u-boot.lds
+++ b/board/freescale/mpc8555cds/u-boot.lds
@@ -34,7 +34,7 @@ SECTIONS
.bootpg 0xFFFFF000 :
{
cpu/mpc85xx/start.o (.bootpg)
- board/cds/mpc8541cds/init.o (.bootpg)
+ board/freescale/mpc8555cds/init.o (.bootpg)
} = 0xffff
/* Read-only sections, merged into text segment: */
@@ -64,7 +64,7 @@ SECTIONS
.text :
{
cpu/mpc85xx/start.o (.text)
- board/cds/mpc8541cds/init.o (.text)
+ board/freescale/mpc8555cds/init.o (.text)
cpu/mpc85xx/traps.o (.text)
cpu/mpc85xx/interrupts.o (.text)
cpu/mpc85xx/cpu_init.o (.text)
--
1.5.3.4
^ permalink raw reply related
* Re: Some git performance measurements..
From: Nicolas Pitre @ 2007-11-29 17:25 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Git Mailing List
In-Reply-To: <alpine.LFD.0.9999.0711282022470.8458@woody.linux-foundation.org>
On Wed, 28 Nov 2007, Linus Torvalds wrote:
> On Wed, 28 Nov 2007, Nicolas Pitre wrote:
>
> > But for a checkout that should actually correspond to a nice linear
> > access.
>
> For the initial check-out, yes. But the thing I timed was just a plain
> "git checkout", which won't actually do any of the blobs if they already
> exist checked-out (which I obviously had), which explains the non-dense
> patterns.
>
> The reason I care about "git checkout" (which is totally uninteresting in
> itself) is that it is a trivial use-case that fairly closely approximates
> two common cases that are *not* uninteresting: switching branches with
> most files unaffected and a fast-forward merge (both of which are the
> "two-way merge" special case).
[...]
> So it's actually fairly common to have "git checkout"-like behaviour with
> no blobs needing to be updated, and the "initial checkout" is in fact
> likely a less usual case. I wonder if we should make the pack-file have
> all the object types in separate regions (we already do that for commits,
> since "git rev-list" kind of operations are dense in the commit).
>
> Making the tree objects dense (the same way the commit objects are) might
> also conceivably speed up "git blame" and path history simplification,
> since those also tend to be "dense" in the tree history but don't actually
> look at the blobs themselves until they change.
Well, see below for the patch that actually split the pack data into
objects of the same type. Doing that "git checkout" on the kernel tree
did improve things for me although not spectacularly.
Current Git warm cache: 0.532s
Current Git cold cache: 17.4s
Patched Git warm cache: 0.521s
Patched Git cold cache: 14.2s
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index 4f44658..b655efd 100644
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
@@ -585,22 +585,43 @@ static off_t write_one(struct sha1file *f,
return offset + size;
}
+static int sort_by_type(const void *_a, const void *_b)
+{
+ const struct object_entry *a = *(struct object_entry **)_a;
+ const struct object_entry *b = *(struct object_entry **)_b;
+
+ /*
+ * Preserve recency order for objects of the same type and reused deltas.
+ */
+ if(a->type == OBJ_REF_DELTA || a->type == OBJ_OFS_DELTA ||
+ b->type == OBJ_REF_DELTA || b->type == OBJ_OFS_DELTA ||
+ a->type == b->type)
+ return (a < b) ? -1 : 1;
+ return a->type - b->type;
+}
+
/* forward declaration for write_pack_file */
static int adjust_perm(const char *path, mode_t mode);
static void write_pack_file(void)
{
- uint32_t i = 0, j;
+ uint32_t i, j;
struct sha1file *f;
off_t offset, offset_one, last_obj_offset = 0;
struct pack_header hdr;
int do_progress = progress >> pack_to_stdout;
uint32_t nr_remaining = nr_result;
+ struct object_entry **sorted_by_type;
if (do_progress)
progress_state = start_progress("Writing objects", nr_result);
written_list = xmalloc(nr_objects * sizeof(*written_list));
+ sorted_by_type = xmalloc(nr_objects * sizeof(*sorted_by_type));
+ for (i = 0; i < nr_objects; i++)
+ sorted_by_type[i] = objects + i;
+ qsort(sorted_by_type, nr_objects, sizeof(*sorted_by_type), sort_by_type);
+ i = 0;
do {
unsigned char sha1[20];
char *pack_tmp_name = NULL;
@@ -625,7 +646,7 @@ static void write_pack_file(void)
nr_written = 0;
for (; i < nr_objects; i++) {
last_obj_offset = offset;
- offset_one = write_one(f, objects + i, offset);
+ offset_one = write_one(f, sorted_by_type[i], offset);
if (!offset_one)
break;
offset = offset_one;
@@ -681,6 +702,7 @@ static void write_pack_file(void)
nr_remaining -= nr_written;
} while (nr_remaining && i < nr_objects);
+ free(sorted_by_type);
free(written_list);
stop_progress(&progress_state);
if (written != nr_result)
^ permalink raw reply related
* Re: problem with git detecting proper renames
From: Linus Torvalds @ 2007-11-29 17:44 UTC (permalink / raw)
To: Kumar Gala; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0711291050440.1711@blarg.am.freescale.net>
On Thu, 29 Nov 2007, Kumar Gala wrote:
>
> I did some git-mv and got the following:
>
> the problem is git seems confused about what file was associated with its
> source.
Well, I wouldn't say "confused". It found multiple identical options for
the source, and picked the first one (where "first one" may not be obvious
to a human, it can depend on an internal hash order).
But if you have the resultant git tree somewhere public (or just send me
the exact "git mv" and revision to recreate), I'll happily give it a look,
to see if we can improve our heuristics to be closer to what a human would
expect.
For example, in this case, it looks like there were two totally identical
"init.S" files that got renamed with the same identical content to two new
names. YOU seem to expect that it would stay as two renames, but from a
content angle, since the two sources were identical, it's a totally
arbitrary choice whether it's a "copy one source to two destinations and
delete the other source" or whether it's two cases of "move one source to
another destination" (and the latter case also has the issue of which way
to move it).
(You also had two identical Makefile's with the exact same issue).
So git doesn't care about how you did the rename, it only cares about the
end result, and the exact same way that it will detect a rename if you
implement it as a "copy file" and then a later "delete old file", it will
also potentially go the other way, or just decide that identical contents
moved in different ways.
But we can certainly tweak the heuristics. For example, if we find
multiple identical renames, right now we just pick one fairly at random,
and have no logic to prefer independent renames over "multiple copies and
a delete". But this code is actually fairly simple, and with a good
example I can easily add heurstics (for example, it probably *is* better
to consider it to be two renames, just because the resulting diff will be
smaller - since a "delete" diff is much larger than a rename diff).
Linus
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox