* [PATCH 5/6] Store the submodule name in struct cached_refs.
From: Michael Haggerty @ 2011-08-12 22:36 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Drew Northup, Jakub Narebski,
Michael Haggerty
In-Reply-To: <1313188589-2330-1-git-send-email-mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 15 +++++++++++----
1 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/refs.c b/refs.c
index 102ed03..8d1055d 100644
--- a/refs.c
+++ b/refs.c
@@ -157,6 +157,8 @@ static struct cached_refs {
char did_packed;
struct ref_list *loose;
struct ref_list *packed;
+ /* The submodule name, or "" for the main repo. */
+ char name[FLEX_ARRAY];
} *cached_refs, *submodule_refs;
static struct ref_list *current_ref;
@@ -181,12 +183,17 @@ static void clear_cached_refs(struct cached_refs *ca)
ca->did_loose = ca->did_packed = 0;
}
-struct cached_refs *create_cached_refs()
+struct cached_refs *create_cached_refs(const char *submodule)
{
+ int len;
struct cached_refs *refs;
- refs = xmalloc(sizeof(struct cached_refs));
+ if (!submodule)
+ submodule = "";
+ len = strlen(submodule) + 1;
+ refs = xmalloc(sizeof(struct cached_refs) + len);
refs->did_loose = refs->did_packed = 0;
refs->loose = refs->packed = NULL;
+ memcpy(refs->name, submodule, len);
return refs;
}
@@ -200,11 +207,11 @@ static struct cached_refs *get_cached_refs(const char *submodule)
{
if (! submodule) {
if (!cached_refs)
- cached_refs = create_cached_refs();
+ cached_refs = create_cached_refs(submodule);
return cached_refs;
} else {
if (!submodule_refs)
- submodule_refs = create_cached_refs();
+ submodule_refs = create_cached_refs(submodule);
else
/* For now, don't reuse the refs cache for submodules. */
clear_cached_refs(submodule_refs);
--
1.7.6.8.gd2879
^ permalink raw reply related
* [PATCH 4/6] Allocate cached_refs objects dynamically
From: Michael Haggerty @ 2011-08-12 22:36 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Drew Northup, Jakub Narebski,
Michael Haggerty
In-Reply-To: <1313188589-2330-1-git-send-email-mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 28 +++++++++++++++++++++-------
1 files changed, 21 insertions(+), 7 deletions(-)
diff --git a/refs.c b/refs.c
index e043555..102ed03 100644
--- a/refs.c
+++ b/refs.c
@@ -157,7 +157,7 @@ static struct cached_refs {
char did_packed;
struct ref_list *loose;
struct ref_list *packed;
-} cached_refs, submodule_refs;
+} *cached_refs, *submodule_refs;
static struct ref_list *current_ref;
static struct ref_list *extra_refs;
@@ -181,6 +181,15 @@ static void clear_cached_refs(struct cached_refs *ca)
ca->did_loose = ca->did_packed = 0;
}
+struct cached_refs *create_cached_refs()
+{
+ struct cached_refs *refs;
+ refs = xmalloc(sizeof(struct cached_refs));
+ refs->did_loose = refs->did_packed = 0;
+ refs->loose = refs->packed = NULL;
+ return refs;
+}
+
/*
* Return a pointer to a cached_refs for the specified submodule. For
* the main repository, use submodule==NULL. The returned structure
@@ -189,12 +198,17 @@ static void clear_cached_refs(struct cached_refs *ca)
*/
static struct cached_refs *get_cached_refs(const char *submodule)
{
- if (! submodule)
- return &cached_refs;
- else {
- /* For now, don't reuse the refs cache for submodules. */
- clear_cached_refs(&submodule_refs);
- return &submodule_refs;
+ if (! submodule) {
+ if (!cached_refs)
+ cached_refs = create_cached_refs();
+ return cached_refs;
+ } else {
+ if (!submodule_refs)
+ submodule_refs = create_cached_refs();
+ else
+ /* For now, don't reuse the refs cache for submodules. */
+ clear_cached_refs(submodule_refs);
+ return submodule_refs;
}
}
--
1.7.6.8.gd2879
^ permalink raw reply related
* [PATCH 3/6] Change the signature of read_packed_refs()
From: Michael Haggerty @ 2011-08-12 22:36 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Drew Northup, Jakub Narebski,
Michael Haggerty
In-Reply-To: <1313188589-2330-1-git-send-email-mhagger@alum.mit.edu>
Change it to return a (struct ref_list *) instead of writing into
a cached_refs structure. (This removes the need to create a
cached_refs structure in resolve_gitlink_packed_ref(), where it
is otherwise unneeded.)
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 14 +++++++-------
1 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/refs.c b/refs.c
index 89840d7..e043555 100644
--- a/refs.c
+++ b/refs.c
@@ -203,7 +203,7 @@ static void invalidate_cached_refs(void)
clear_cached_refs(get_cached_refs(NULL));
}
-static void read_packed_refs(FILE *f, struct cached_refs *cached_refs)
+static struct ref_list *read_packed_refs(FILE *f)
{
struct ref_list *list = NULL;
struct ref_list *last = NULL;
@@ -235,7 +235,7 @@ static void read_packed_refs(FILE *f, struct cached_refs *cached_refs)
!get_sha1_hex(refline + 1, sha1))
hashcpy(last->peeled, sha1);
}
- cached_refs->packed = sort_ref_list(list);
+ return sort_ref_list(list);
}
void add_extra_ref(const char *name, const unsigned char *sha1, int flag)
@@ -262,7 +262,7 @@ static struct ref_list *get_packed_refs(const char *submodule)
FILE *f = fopen(packed_refs_file, "r");
refs->packed = NULL;
if (f) {
- read_packed_refs(f, refs);
+ refs->packed = read_packed_refs(f);
fclose(f);
}
refs->did_packed = 1;
@@ -389,7 +389,7 @@ static struct ref_list *get_loose_refs(const char *submodule)
static int resolve_gitlink_packed_ref(char *name, int pathlen, const char *refname, unsigned char *result)
{
FILE *f;
- struct cached_refs refs;
+ struct ref_list *packed_refs;
struct ref_list *ref;
int retval;
@@ -397,9 +397,9 @@ static int resolve_gitlink_packed_ref(char *name, int pathlen, const char *refna
f = fopen(name, "r");
if (!f)
return -1;
- read_packed_refs(f, &refs);
+ packed_refs = read_packed_refs(f);
fclose(f);
- ref = refs.packed;
+ ref = packed_refs;
retval = -1;
while (ref) {
if (!strcmp(ref->name, refname)) {
@@ -409,7 +409,7 @@ static int resolve_gitlink_packed_ref(char *name, int pathlen, const char *refna
}
ref = ref->next;
}
- free_ref_list(refs.packed);
+ free_ref_list(packed_refs);
return retval;
}
--
1.7.6.8.gd2879
^ permalink raw reply related
* [PATCH 2/6] Access reference caches only through new function get_cached_refs().
From: Michael Haggerty @ 2011-08-12 22:36 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Drew Northup, Jakub Narebski,
Michael Haggerty
In-Reply-To: <1313188589-2330-1-git-send-email-mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 54 +++++++++++++++++++++++++++++++-----------------------
1 files changed, 31 insertions(+), 23 deletions(-)
diff --git a/refs.c b/refs.c
index b0c8308..89840d7 100644
--- a/refs.c
+++ b/refs.c
@@ -181,9 +181,26 @@ static void clear_cached_refs(struct cached_refs *ca)
ca->did_loose = ca->did_packed = 0;
}
+/*
+ * Return a pointer to a cached_refs for the specified submodule. For
+ * the main repository, use submodule==NULL. The returned structure
+ * will be allocated and initialized but not necessarily populated; it
+ * should not be freed.
+ */
+static struct cached_refs *get_cached_refs(const char *submodule)
+{
+ if (! submodule)
+ return &cached_refs;
+ else {
+ /* For now, don't reuse the refs cache for submodules. */
+ clear_cached_refs(&submodule_refs);
+ return &submodule_refs;
+ }
+}
+
static void invalidate_cached_refs(void)
{
- clear_cached_refs(&cached_refs);
+ clear_cached_refs(get_cached_refs(NULL));
}
static void read_packed_refs(FILE *f, struct cached_refs *cached_refs)
@@ -234,19 +251,14 @@ void clear_extra_refs(void)
static struct ref_list *get_packed_refs(const char *submodule)
{
- const char *packed_refs_file;
- struct cached_refs *refs;
+ struct cached_refs *refs = get_cached_refs(submodule);
- if (submodule) {
- packed_refs_file = git_path_submodule(submodule, "packed-refs");
- refs = &submodule_refs;
- free_ref_list(refs->packed);
- } else {
- packed_refs_file = git_path("packed-refs");
- refs = &cached_refs;
- }
-
- if (!refs->did_packed || submodule) {
+ if (!refs->did_packed) {
+ const char *packed_refs_file;
+ if (submodule)
+ packed_refs_file = git_path_submodule(submodule, "packed-refs");
+ else
+ packed_refs_file = git_path("packed-refs");
FILE *f = fopen(packed_refs_file, "r");
refs->packed = NULL;
if (f) {
@@ -361,17 +373,13 @@ void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname)
static struct ref_list *get_loose_refs(const char *submodule)
{
- if (submodule) {
- free_ref_list(submodule_refs.loose);
- submodule_refs.loose = get_ref_dir(submodule, "refs", NULL);
- return submodule_refs.loose;
- }
+ struct cached_refs *refs = get_cached_refs(submodule);
- if (!cached_refs.did_loose) {
- cached_refs.loose = get_ref_dir(NULL, "refs", NULL);
- cached_refs.did_loose = 1;
+ if (!refs->did_loose) {
+ refs->loose = get_ref_dir(submodule, "refs", NULL);
+ refs->did_loose = 1;
}
- return cached_refs.loose;
+ return refs->loose;
}
/* We allow "recursive" symbolic refs. Only within reason, though */
--
1.7.6.8.gd2879
^ permalink raw reply related
* [PATCH 1/6] Extract a function clear_cached_refs()
From: Michael Haggerty @ 2011-08-12 22:36 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Drew Northup, Jakub Narebski,
Michael Haggerty
In-Reply-To: <1313188589-2330-1-git-send-email-mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 9 ++++++---
1 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/refs.c b/refs.c
index 6f313a9..b0c8308 100644
--- a/refs.c
+++ b/refs.c
@@ -171,10 +171,8 @@ static void free_ref_list(struct ref_list *list)
}
}
-static void invalidate_cached_refs(void)
+static void clear_cached_refs(struct cached_refs *ca)
{
- struct cached_refs *ca = &cached_refs;
-
if (ca->did_loose && ca->loose)
free_ref_list(ca->loose);
if (ca->did_packed && ca->packed)
@@ -183,6 +181,11 @@ static void invalidate_cached_refs(void)
ca->did_loose = ca->did_packed = 0;
}
+static void invalidate_cached_refs(void)
+{
+ clear_cached_refs(&cached_refs);
+}
+
static void read_packed_refs(FILE *f, struct cached_refs *cached_refs)
{
struct ref_list *list = NULL;
--
1.7.6.8.gd2879
^ permalink raw reply related
* [PATCH 0/6] Retain caches of submodule refs
From: Michael Haggerty @ 2011-08-12 22:36 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Drew Northup, Jakub Narebski,
Michael Haggerty
...and work towards storing refs hierarchically.
Currently, the refs for submodules are put into a cache when accessed
but the cache is never reused. Whenever the refs for a submodule are
accessed, the cache is cleared and refilled, even if the submodule
cache already contains data for that submodule. Essentially, the
submodule cache only controls the lifetime of the data structures.
The main module is currently stored in a separate cache that is reused
properly.
This patch series institutes proper caching of submodule refs:
maintain a linked list of caches for each submodule, and add a new
entry whenever the refs for a new submodule are accessed. Also store
the cache for the main project in the same linked list for uniformity.
This change accomplishes two things:
* Proper caching of submodule refs. I'm not sure whether this is a
significant win by itself; it depends on the usage patterns and I'm
not too familiar with how submodules are used. But it seems pretty
clear that this is an improvement on the old kludge.
* It is a first step towards storing refs hierarchically *within*
modules. My plan is to build out "struct cached_refs" into a
hierarchical data structure mimicking the reference namespace
hierarchy, with one cached_ref instance for each "directory" of
refs. Then (the real goal) change the code to only populate the
parts of the cache hierarchy that are actually accessed.
I believe that this change is useful by itself, self-contained, and
ready to be committed. I plan to build the hierarchical-refs changes
on top of it. But if it is preferred, I can submit this series plus
the hierarchical-refs patches as a single patch series (once the
latter is done, which will still take some time).
This patch series applies on top of "next" rather than "master"
because it would otherwise conflict with the changes made by
js/ref-namespaces.
I am on vacation and don't know when I will have internet access, so
please don't be offended if I don't respond quickly to feedback.
Michael Haggerty (6):
Extract a function clear_cached_refs()
Access reference caches only through new function get_cached_refs().
Change the signature of read_packed_refs()
Allocate cached_refs objects dynamically
Store the submodule name in struct cached_refs.
Retain caches of submodule refs
refs.c | 106 ++++++++++++++++++++++++++++++++++++++++++++--------------------
1 files changed, 73 insertions(+), 33 deletions(-)
--
1.7.6.8.gd2879
^ permalink raw reply
* Re: Suggestions to make git easier to understand
From: Jeff King @ 2011-08-12 22:26 UTC (permalink / raw)
To: Jonathan Nieder; +Cc: Philippe Vaucher, git, Rafael Magana
In-Reply-To: <20110811221627.GA32005@elie.gateway.2wire.net>
On Thu, Aug 11, 2011 at 05:16:27PM -0500, Jonathan Nieder wrote:
> > http://raflabs.com/blogs/silence-is-foo/2011/04/07/staging-area-index-cache-git/
> >
> > I thought it made some good points about git being kinda confusing,
> > for example sentences like "Changed but not updated" in git status
> > could use a better sentence like "Changed but not in the index".
>
> Sounds reasonable (well, with some more precise wording to reflect
> that this means "changed but not all changes are reflected in the
> index").
Didn't we fix this already in 8009d83 (Better "Changed but not updated"
message in git-status, 2010-11-02)? Since v1.7.4, "git status" has
"Changes not staged for commit".
-Peff
^ permalink raw reply
* Re: [PATCHv2 27/56] string-list: Add API to remove an item from an unsorted list
From: Elijah Newren @ 2011-08-12 22:14 UTC (permalink / raw)
To: Johannes Sixt; +Cc: gitster, git, Jim Foucar, Johannes Sixt
In-Reply-To: <4E44CF9D.8030501@viscovery.net>
On Fri, Aug 12, 2011 at 1:00 AM, Johannes Sixt <j.sixt@viscovery.net> wrote:
> Am 8/12/2011 7:20, schrieb Elijah Newren:
>> Here's an attempt for a delete_item API (note: only compile-tested).
>
> Seriously? You haven't even tested this patch, and still don't mark it
> with RFC?
>
>> Bike-shed painters welcome: delete_item, remove_item, free_item?
>
> You should know that a sentence like this shouldn't appear in the commit
> message.
>
> Yeah, I know, you just copy-pasted my email text. But that was not a
> commit message. Perhaps like this:
You are right. I apologize; I messed up here.
However, I am unclear what you mean by not even testing the patch,
though. I couldn't find any unit-test harness or any other kind of
testsuite for the string_list API. I did review the code to make sure
it looked right to me, added a use of your new function, and ran the
standard testsuite in addition to my "re-merge all merges from
git.git" testcase. I even single stepped through the code in a
debugger for good measure. What testing did you want to see in
particular?
^ permalink raw reply
* Re: [PATCHv2 00/57] Re-roll of en/merge-recursive from pu
From: Elijah Newren @ 2011-08-12 21:59 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Jim Foucar
In-Reply-To: <7vei0rnprt.fsf@alter.siamese.dyndns.org>
Hi,
On Thu, Aug 11, 2011 at 11:48 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Avoiding silent mismerges is of course one of the most important criteria,
> but we also need to make sure that a conflicted state left in the index
> and the working tree files must not be harder to reconcile than what we
> have been giving our users---otherwise the change will be seen as a
> regression by them.
Yeah, good point. I tried re-running my previous re-merge all merges
in git.git testcase, modified so that when both versions of git
reported a conflict I would compare the output of 'git ls-files -s'.
That uncovered a regression. I think I know the fix but I need to
retest and do some more checks.
^ permalink raw reply
* [PATCH 7/7] Unroll the loop over passes
From: Michael Haggerty @ 2011-08-12 21:43 UTC (permalink / raw)
To: git; +Cc: gitster, Michael Haggerty
In-Reply-To: <1313185390-19724-1-git-send-email-mhagger@alum.mit.edu>
The passes no longer share much code, and the unrolled code is easier
to understand.
Use a new index variable instead of num_attr for the second loop, as
we are no longer counting attributes but rather indexing through them.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
attr.c | 51 ++++++++++++++++++++++++++-------------------------
1 files changed, 26 insertions(+), 25 deletions(-)
diff --git a/attr.c b/attr.c
index b56542e..6abaaec 100644
--- a/attr.c
+++ b/attr.c
@@ -191,10 +191,9 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
int lineno, int macro_ok)
{
int namelen;
- int num_attr;
+ int num_attr, i;
const char *cp, *name, *states;
struct match_attr *res = NULL;
- int pass;
int is_macro;
cp = line + strspn(line, blank);
@@ -226,30 +225,32 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
states = name + namelen;
states += strspn(states, blank);
- for (pass = 0; pass < 2; pass++) {
- /* pass 0 counts and allocates, pass 1 fills */
- for (cp = states, num_attr = 0; *cp; num_attr++) {
- cp = parse_attr(src, lineno, cp,
- pass ? &(res->state[num_attr]) : NULL);
- if (!cp)
- return NULL;
- }
- if (pass)
- break;
- res = xcalloc(1,
- sizeof(*res) +
- sizeof(struct attr_state) * num_attr +
- (is_macro ? 0 : namelen + 1));
- if (is_macro)
- res->u.attr = git_attr_internal(name, namelen);
- else {
- res->u.pattern = (char *)&(res->state[num_attr]);
- memcpy(res->u.pattern, name, namelen);
- res->u.pattern[namelen] = 0;
- }
- res->is_macro = is_macro;
- res->num_attr = num_attr;
+ /* First pass to count the attr_states */
+ for (cp = states, num_attr = 0; *cp; num_attr++) {
+ cp = parse_attr(src, lineno, cp, NULL);
+ if (!cp)
+ return NULL;
}
+
+ res = xcalloc(1,
+ sizeof(*res) +
+ sizeof(struct attr_state) * num_attr +
+ (is_macro ? 0 : namelen + 1));
+ if (is_macro)
+ res->u.attr = git_attr_internal(name, namelen);
+ else {
+ res->u.pattern = (char *)&(res->state[num_attr]);
+ memcpy(res->u.pattern, name, namelen);
+ res->u.pattern[namelen] = 0;
+ }
+ res->is_macro = is_macro;
+ res->num_attr = num_attr;
+
+ /* Second pass to fill the attr_states */
+ for (cp = states, i = 0; *cp; i++) {
+ cp = parse_attr(src, lineno, cp, &(res->state[i]));
+ }
+
return res;
}
--
1.7.6.8.gd2879
^ permalink raw reply related
* [PATCH 6/7] Change while loop into for loop
From: Michael Haggerty @ 2011-08-12 21:43 UTC (permalink / raw)
To: git; +Cc: gitster, Michael Haggerty
In-Reply-To: <1313185390-19724-1-git-send-email-mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
attr.c | 5 +----
1 files changed, 1 insertions(+), 4 deletions(-)
diff --git a/attr.c b/attr.c
index a7d1aa9..b56542e 100644
--- a/attr.c
+++ b/attr.c
@@ -228,14 +228,11 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
for (pass = 0; pass < 2; pass++) {
/* pass 0 counts and allocates, pass 1 fills */
- num_attr = 0;
- cp = states;
- while (*cp) {
+ for (cp = states, num_attr = 0; *cp; num_attr++) {
cp = parse_attr(src, lineno, cp,
pass ? &(res->state[num_attr]) : NULL);
if (!cp)
return NULL;
- num_attr++;
}
if (pass)
break;
--
1.7.6.8.gd2879
^ permalink raw reply related
* [PATCH 5/7] Determine the start of the states outside of the pass loop
From: Michael Haggerty @ 2011-08-12 21:43 UTC (permalink / raw)
To: git; +Cc: gitster, Michael Haggerty
In-Reply-To: <1313185390-19724-1-git-send-email-mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
attr.c | 8 +++++---
1 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/attr.c b/attr.c
index f23f62a..a7d1aa9 100644
--- a/attr.c
+++ b/attr.c
@@ -192,7 +192,7 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
{
int namelen;
int num_attr;
- const char *cp, *name;
+ const char *cp, *name, *states;
struct match_attr *res = NULL;
int pass;
int is_macro;
@@ -223,11 +223,13 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
else
is_macro = 0;
+ states = name + namelen;
+ states += strspn(states, blank);
+
for (pass = 0; pass < 2; pass++) {
/* pass 0 counts and allocates, pass 1 fills */
num_attr = 0;
- cp = name + namelen;
- cp = cp + strspn(cp, blank);
+ cp = states;
while (*cp) {
cp = parse_attr(src, lineno, cp,
pass ? &(res->state[num_attr]) : NULL);
--
1.7.6.8.gd2879
^ permalink raw reply related
* [PATCH 4/7] Change parse_attr() to take a pointer to struct attr_state
From: Michael Haggerty @ 2011-08-12 21:43 UTC (permalink / raw)
To: git; +Cc: gitster, Michael Haggerty
In-Reply-To: <1313185390-19724-1-git-send-email-mhagger@alum.mit.edu>
parse_attr() only needs access to the attr_state to which it should
store its results, not to the whole match_attr structure. This change
also removes the need for it to know num_attr. Change its signature
accordingly and add a comment.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
attr.c | 17 +++++++++++------
1 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/attr.c b/attr.c
index cac550d..f23f62a 100644
--- a/attr.c
+++ b/attr.c
@@ -139,8 +139,15 @@ struct match_attr {
static const char blank[] = " \t\r\n";
+/*
+ * Parse a whitespace-delimited attribute state (i.e., "attr",
+ * "-attr", "!attr", or "attr=value") from the string starting at src.
+ * If e is not NULL, write the results to *e. Return a pointer to the
+ * remainder of the string (with leading whitespace removed), or NULL
+ * if there was an error.
+ */
static const char *parse_attr(const char *src, int lineno, const char *cp,
- int num_attr, struct match_attr *res)
+ struct attr_state *e)
{
const char *ep, *equals;
int len;
@@ -153,7 +160,7 @@ static const char *parse_attr(const char *src, int lineno, const char *cp,
len = equals - cp;
else
len = ep - cp;
- if (!res) {
+ if (!e) {
if (*cp == '-' || *cp == '!') {
cp++;
len--;
@@ -165,9 +172,6 @@ static const char *parse_attr(const char *src, int lineno, const char *cp,
return NULL;
}
} else {
- struct attr_state *e;
-
- e = &(res->state[num_attr]);
if (*cp == '-' || *cp == '!') {
e->setto = (*cp == '-') ? ATTR__FALSE : ATTR__UNSET;
cp++;
@@ -225,7 +229,8 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
cp = name + namelen;
cp = cp + strspn(cp, blank);
while (*cp) {
- cp = parse_attr(src, lineno, cp, num_attr, res);
+ cp = parse_attr(src, lineno, cp,
+ pass ? &(res->state[num_attr]) : NULL);
if (!cp)
return NULL;
num_attr++;
--
1.7.6.8.gd2879
^ permalink raw reply related
* [PATCH 3/7] Increment num_attr in parse_attr_line(), not parse_attr()
From: Michael Haggerty @ 2011-08-12 21:43 UTC (permalink / raw)
To: git; +Cc: gitster, Michael Haggerty
In-Reply-To: <1313185390-19724-1-git-send-email-mhagger@alum.mit.edu>
num_attr is incremented iff parse_attr() returns non-NULL. So do the
counting in parse_attr_line() instead of within parse_attr(). This
allows an integer rather than a pointer to an integer to be passed to
parse_attr().
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
attr.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/attr.c b/attr.c
index c33e413..cac550d 100644
--- a/attr.c
+++ b/attr.c
@@ -140,7 +140,7 @@ struct match_attr {
static const char blank[] = " \t\r\n";
static const char *parse_attr(const char *src, int lineno, const char *cp,
- int *num_attr, struct match_attr *res)
+ int num_attr, struct match_attr *res)
{
const char *ep, *equals;
int len;
@@ -167,7 +167,7 @@ static const char *parse_attr(const char *src, int lineno, const char *cp,
} else {
struct attr_state *e;
- e = &(res->state[*num_attr]);
+ e = &(res->state[num_attr]);
if (*cp == '-' || *cp == '!') {
e->setto = (*cp == '-') ? ATTR__FALSE : ATTR__UNSET;
cp++;
@@ -180,7 +180,6 @@ static const char *parse_attr(const char *src, int lineno, const char *cp,
}
e->attr = git_attr_internal(cp, len);
}
- (*num_attr)++;
return ep + strspn(ep, blank);
}
@@ -226,9 +225,10 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
cp = name + namelen;
cp = cp + strspn(cp, blank);
while (*cp) {
- cp = parse_attr(src, lineno, cp, &num_attr, res);
+ cp = parse_attr(src, lineno, cp, num_attr, res);
if (!cp)
return NULL;
+ num_attr++;
}
if (pass)
break;
--
1.7.6.8.gd2879
^ permalink raw reply related
* [PATCH 2/7] Document struct match_attr
From: Michael Haggerty @ 2011-08-12 21:43 UTC (permalink / raw)
To: git; +Cc: gitster, Michael Haggerty
In-Reply-To: <1313185390-19724-1-git-send-email-mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
attr.c | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/attr.c b/attr.c
index 6bc7ae9..c33e413 100644
--- a/attr.c
+++ b/attr.c
@@ -113,6 +113,20 @@ struct attr_state {
const char *setto;
};
+/*
+ * One rule, as from a .gitattributes file.
+ *
+ * If is_macro is true, then u.attr is a pointer to the git_attr being
+ * defined.
+ *
+ * If is_macro is false, then u.pattern points at the filename pattern
+ * to which the rule applies. (The memory pointed to is part of the
+ * memory block allocated for the match_attr instance.)
+ *
+ * In either case, num_attr is the number of attributes affected by
+ * this rule, and state is an array listing them. The attributes are
+ * listed as they appear in the file (macros unexpanded).
+ */
struct match_attr {
union {
char *pattern;
--
1.7.6.8.gd2879
^ permalink raw reply related
* [PATCH 1/7] Add a file comment
From: Michael Haggerty @ 2011-08-12 21:43 UTC (permalink / raw)
To: git; +Cc: gitster, Michael Haggerty
In-Reply-To: <1313185390-19724-1-git-send-email-mhagger@alum.mit.edu>
Consolidate here a few general comments plus links to other
documentation. Delete a comment with an out-of-date description of
the .gitattributes file format.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
attr.c | 26 ++++++++++----------------
1 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/attr.c b/attr.c
index f6b3f7e..6bc7ae9 100644
--- a/attr.c
+++ b/attr.c
@@ -1,3 +1,12 @@
+/*
+ * Handle git attributes. See gitattributes(5) for a description of
+ * the file syntax, and Documentation/technical/api-gitattributes.txt
+ * for a description of the API.
+ *
+ * One basic design decision here is that we are not going to support
+ * an insanely large number of attributes.
+ */
+
#define NO_THE_INDEX_COMPATIBILITY_MACROS
#include "cache.h"
#include "exec_cmd.h"
@@ -13,12 +22,7 @@ static const char git_attr__unknown[] = "(builtin)unknown";
static const char *attributes_file;
-/*
- * The basic design decision here is that we are not going to have
- * insanely large number of attributes.
- *
- * This is a randomly chosen prime.
- */
+/* This is a randomly chosen prime. */
#define HASHSIZE 257
#ifndef DEBUG_ATTR
@@ -103,16 +107,6 @@ struct git_attr *git_attr(const char *name)
return git_attr_internal(name, strlen(name));
}
-/*
- * .gitattributes file is one line per record, each of which is
- *
- * (1) glob pattern.
- * (2) whitespace
- * (3) whitespace separated list of attribute names, each of which
- * could be prefixed with '-' to mean "set to false", '!' to mean
- * "unset".
- */
-
/* What does a matched pattern decide? */
struct attr_state {
struct git_attr *attr;
--
1.7.6.8.gd2879
^ permalink raw reply related
* [PATCH 0/7] Comments and refactoring in attr.c
From: Michael Haggerty @ 2011-08-12 21:43 UTC (permalink / raw)
To: git; +Cc: gitster, Michael Haggerty
This patch series adds comments for some non-obvious things in attr.c,
simplifies the interface of parse_attr(), and unrolls the loop over
passes in parse_attr_line() (which IMO makes the code easier to
understand). It does not change the observable behavior in any way.
The patch series is against master, but can be rebased to next without
conflicts.
Michael Haggerty (7):
Add a file comment
Document struct match_attr
Increment num_attr in parse_attr_line(), not parse_attr()
Change parse_attr() to take a pointer to struct attr_state
Determine the start of the states outside of the pass loop
Change while loop into for loop
Unroll the loop over passes
attr.c | 113 +++++++++++++++++++++++++++++++++++----------------------------
1 files changed, 63 insertions(+), 50 deletions(-)
--
1.7.6.8.gd2879
^ permalink raw reply
* Re: [PATCH v3 1/2] rev-parse: add option --is-well-formed-git-dir [path]
From: Junio C Hamano @ 2011-08-12 20:57 UTC (permalink / raw)
To: Fredrik Gustafsson; +Cc: git, jens.lehmann, hvoigt
In-Reply-To: <1313178913-25617-2-git-send-email-iveqy@iveqy.com>
Fredrik Gustafsson <iveqy@iveqy.com> writes:
> Check if [path] is a valid git-dir or a valid git-file that points
> to a valid git-dir.
On Subject, here, and in the doc, I do not think you meant "[path]" (which
typically means "you do not have to have anything, but you are allowed to
have a path, if you do write something here."). Perhaps you meant to say
<path> instead (which is how most if not all of the documentation mark a
placeholder in a description)?
^ permalink raw reply
* Re: Overriding ~/.gitconfig using GIT_CONFIG
From: Richard Purdie @ 2011-08-12 20:44 UTC (permalink / raw)
To: Junio C Hamano
Cc: Daniel Barkalow, Nguyễn Thái Ngọc Duy,
GIT Mailing-list
In-Reply-To: <7vmxfemnc4.fsf@alter.siamese.dyndns.org>
On Fri, 2011-08-12 at 12:39 -0700, Junio C Hamano wrote:
> Junio C Hamano <gitster@pobox.com> writes:
>
> > Richard Purdie <rpurdie@rpsys.net> writes:
> >
> >> Looking through the manuals/code, it suggests I should be able to do:
> >>
> >> GIT_CONFIG=/dev/null git XXX
> >>
> >> and all should work happily. It doesn't though. As an example, with a
> >> ~/.gitconfig, "GIT_CONFIG=/dev/null git fetch --all" is clearly
> >> accessing the file in ~ and then acting upon it.
> >
> > If the manual says the above is expected for any value of XXX, then that
> > is a bug in the manual since mid 2008, I think.
> >
> > See dc87183 (Only use GIT_CONFIG in "git config", not other programs,
> > 2008-06-30).
> >
> > I _think_ these days a workaround to force a known config is to set HOME
> > to a value that has a known .gitconfig (or no such file), and decline
> > usage of /etc/git.config by exporting GIT_CONFIG_NOSYSTEM.
>
> Side note. Here is what dc87183 says:
>
> commit dc87183189b54441e315d35d48983d80ab085299
> Author: Daniel Barkalow <barkalow@iabervon.org>
> Date: Mon Jun 30 03:37:47 2008 -0400
>
> Only use GIT_CONFIG in "git config", not other programs
>
> For everything other than using "git config" to read or write a
> git-style config file that isn't the current repo's config file,
> GIT_CONFIG was actively detrimental. Rather than argue over which
> programs are important enough to have work anyway, just fix all of
> them at the root.
>
> Also removes GIT_LOCAL_CONFIG, which would only be useful for programs
> that do want to use global git-specific config, but not the repo's own
> git-specific config, and want to use some other, presumably
> git-specific config. Despite being documented, I can't find any sign that
> it was ever used.
>
> Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
>
> It clearly explains the reason why LOCAL_CONFIG was removed (the reader
> does not have to agree with "I can't find any sign that it was ever used",
> though), but I cannot read from the first paragraph the reason why it was
> felt necessary not to honor GIT_CONFIG in other programs, i.e. "was
> actively detrimental" is not backed by any example in the paragraph. I can
> sort of sense from "Rather than argue over..." that there may have been a
> discussion on the list, and reading the archive from that timeframe may
> reveal why many felt it was not a good idea.
>
> Daniel, do you recall the context?
I went digging and this looks like as good a summary as any of the posts
around that time:
http://marc.info/?l=git&m=121476432303314&w=2
It sounds like if you specified GIT_CONFIG when making a clone it would
end up writing the config file specified rather than .git/config.
My problem isn't that I want to specify a specific .gitconfig file, I
just need it to ignore the one in $HOME. I'm happy for the .git/config
file to be used, in fact I need it to be.
I noticed 8f323c00dd3c9b396b01a1aeea74f7dfd061bb7f was committed which
removed GIT_CONFIG_NOGLOBAL support which is the other way to address
the problem. Could we add that back?
I appreciate I can set $HOME to something but that means creating an
empty directory to point at and feels rather like a work around rather
than a solution.
Cheers,
Richard
--
Linux Foundation
http://www.yoctoproject.org/
^ permalink raw reply
* [PATCH v3 1/2] rev-parse: add option --is-well-formed-git-dir [path]
From: Fredrik Gustafsson @ 2011-08-12 19:55 UTC (permalink / raw)
To: git; +Cc: iveqy, jens.lehmann, hvoigt, gitster
In-Reply-To: <1313178913-25617-1-git-send-email-iveqy@iveqy.com>
Check if [path] is a valid git-dir or a valid git-file that points
to a valid git-dir.
We want tests to be independent from the fact that a git-dir may
be a git-file. Thus we changed tests to use this feature.
Signed-off-by: Fredrik Gustafsson <iveqy@iveqy.com>
Mentored-by: Jens Lehmann <Jens.Lehmann@web.de>
Mentored-by: Heiko Voigt <hvoigt@hvoigt.net>
---
Documentation/git-rev-parse.txt | 4 ++
builtin/rev-parse.c | 8 +++
cache.h | 1 +
setup.c | 7 +++
t/t7400-submodule-basic.sh | 4 +-
t/t7403-submodule-sync.sh | 5 +-
t/t7407-submodule-foreach.sh | 97 ++++++++++++++++++++-------------------
7 files changed, 75 insertions(+), 51 deletions(-)
diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index 42c9676..3ce81c0 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -180,6 +180,10 @@ print a message to stderr and exit with nonzero status.
<args>...::
Flags and parameters to be parsed.
+--is-well-formed-git-dir [path]::
+ Check if [path] is a valid git-dir or a git-file pointing to a valid
+ git-dir. If [path] is a valid git-dir the resolved path to git-dir will
+ be printed.
include::revisions.txt[]
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 4c19f84..21ac43f 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -468,6 +468,14 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
return 0;
}
+ if (argc > 2 && !strcmp(argv[1], "--is-well-formed-git-dir")) {
+ const char *gitdir = resolve_gitdir(argv[2]);
+ if (!gitdir)
+ die("not a gitdir '%s'", argv[2]);
+ puts(gitdir);
+ return 0;
+ }
+
if (argc > 1 && !strcmp("-h", argv[1]))
usage(builtin_rev_parse_usage);
diff --git a/cache.h b/cache.h
index 9e12d55..550f632 100644
--- a/cache.h
+++ b/cache.h
@@ -436,6 +436,7 @@ extern char *get_graft_file(void);
extern int set_git_dir(const char *path);
extern const char *get_git_work_tree(void);
extern const char *read_gitfile_gently(const char *path);
+extern const char *resolve_gitdir(const char *suspect);
extern void set_git_work_tree(const char *tree);
#define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
diff --git a/setup.c b/setup.c
index 5ea5502..efad002 100644
--- a/setup.c
+++ b/setup.c
@@ -808,3 +808,10 @@ const char *setup_git_directory(void)
{
return setup_git_directory_gently(NULL);
}
+
+const char *resolve_gitdir(const char *suspect)
+{
+ if (is_git_directory(suspect))
+ return suspect;
+ return read_gitfile_gently(suspect);
+}
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index 14dc927..4df53e5 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -360,10 +360,10 @@ test_expect_success 'update --init' '
git submodule update init > update.out &&
cat update.out &&
test_i18ngrep "not initialized" update.out &&
- ! test -d init/.git &&
+ test_must_fail git rev-parse --is-well-formed-git-dir init/.git &&
git submodule update --init init &&
- test -d init/.git
+ git rev-parse --is-well-formed-git-dir init/.git
'
test_expect_success 'do not add files from a submodule' '
diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh
index 95ffe34..3620215 100755
--- a/t/t7403-submodule-sync.sh
+++ b/t/t7403-submodule-sync.sh
@@ -56,8 +56,9 @@ test_expect_success '"git submodule sync" should update submodule URLs' '
git pull --no-recurse-submodules &&
git submodule sync
) &&
- test -d "$(git config -f super-clone/submodule/.git/config \
- remote.origin.url)" &&
+ test -d "$(cd super-clone/submodule &&
+ git config remote.origin.url
+ )" &&
(cd super-clone/submodule &&
git checkout master &&
git pull
diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh
index be745fb..1a974e2 100755
--- a/t/t7407-submodule-foreach.sh
+++ b/t/t7407-submodule-foreach.sh
@@ -118,19 +118,19 @@ test_expect_success 'use "submodule foreach" to checkout 2nd level submodule' '
git clone super clone2 &&
(
cd clone2 &&
- test ! -d sub1/.git &&
- test ! -d sub2/.git &&
- test ! -d sub3/.git &&
- test ! -d nested1/.git &&
+ test_must_fail git rev-parse --is-well-formed-git-dir sub1/.git &&
+ test_must_fail git rev-parse --is-well-formed-git-dir sub2/.git &&
+ test_must_fail git rev-parse --is-well-formed-git-dir sub3/.git &&
+ test_must_fail git rev-parse --is-well-formed-git-dir nested1/.git &&
git submodule update --init &&
- test -d sub1/.git &&
- test -d sub2/.git &&
- test -d sub3/.git &&
- test -d nested1/.git &&
- test ! -d nested1/nested2/.git &&
+ git rev-parse --is-well-formed-git-dir sub1/.git &&
+ git rev-parse --is-well-formed-git-dir sub2/.git &&
+ git rev-parse --is-well-formed-git-dir sub3/.git &&
+ git rev-parse --is-well-formed-git-dir nested1/.git &&
+ test_must_fail git rev-parse --is-well-formed-git-dir nested1/nested2/.git &&
git submodule foreach "git submodule update --init" &&
- test -d nested1/nested2/.git &&
- test ! -d nested1/nested2/nested3/.git
+ git rev-parse --is-well-formed-git-dir nested1/nested1/nested2/.git
+ test_must_fail git rev-parse --is-well-formed-git-dir nested1/nested2/nested3/.git
)
'
@@ -138,8 +138,8 @@ test_expect_success 'use "foreach --recursive" to checkout all submodules' '
(
cd clone2 &&
git submodule foreach --recursive "git submodule update --init" &&
- test -d nested1/nested2/nested3/.git &&
- test -d nested1/nested2/nested3/submodule/.git
+ git rev-parse --is-well-formed-git-dir nested1/nested2/nested3/.git &&
+ git rev-parse --is-well-formed-git-dir nested1/nested2/nested3/submodule/.git
)
'
@@ -183,18 +183,18 @@ test_expect_success 'use "update --recursive" to checkout all submodules' '
git clone super clone3 &&
(
cd clone3 &&
- test ! -d sub1/.git &&
- test ! -d sub2/.git &&
- test ! -d sub3/.git &&
- test ! -d nested1/.git &&
+ test_must_fail git rev-parse --is-well-formed-git-dir sub1/.git &&
+ test_must_fail git rev-parse --is-well-formed-git-dir sub2/.git &&
+ test_must_fail git rev-parse --is-well-formed-git-dir sub3/.git &&
+ test_must_fail git rev-parse --is-well-formed-git-dir nested1/.git &&
git submodule update --init --recursive &&
- test -d sub1/.git &&
- test -d sub2/.git &&
- test -d sub3/.git &&
- test -d nested1/.git &&
- test -d nested1/nested2/.git &&
- test -d nested1/nested2/nested3/.git &&
- test -d nested1/nested2/nested3/submodule/.git
+ git rev-parse --is-well-formed-git-dir sub1/.git &&
+ git rev-parse --is-well-formed-git-dir sub2/.git &&
+ git rev-parse --is-well-formed-git-dir sub3/.git &&
+ git rev-parse --is-well-formed-git-dir nested1/.git &&
+ git rev-parse --is-well-formed-git-dir nested1/nested2/.git &&
+ git rev-parse --is-well-formed-git-dir nested1/nested2/nested3/.git &&
+ git rev-parse --is-well-formed-git-dir nested1/nested2/nested3/submodule/.git
)
'
@@ -247,14 +247,17 @@ test_expect_success 'ensure "status --cached --recursive" preserves the --cached
test_expect_success 'use "git clone --recursive" to checkout all submodules' '
git clone --recursive super clone4 &&
- test -d clone4/.git &&
- test -d clone4/sub1/.git &&
- test -d clone4/sub2/.git &&
- test -d clone4/sub3/.git &&
- test -d clone4/nested1/.git &&
- test -d clone4/nested1/nested2/.git &&
- test -d clone4/nested1/nested2/nested3/.git &&
- test -d clone4/nested1/nested2/nested3/submodule/.git
+ (
+ cd clone4 &&
+ git rev-parse --is-well-formed-git-dir .git &&
+ git rev-parse --is-well-formed-git-dir sub1/.git &&
+ git rev-parse --is-well-formed-git-dir sub2/.git &&
+ git rev-parse --is-well-formed-git-dir sub3/.git &&
+ git rev-parse --is-well-formed-git-dir nested1/.git &&
+ git rev-parse --is-well-formed-git-dir nested1/nested2/.git &&
+ git rev-parse --is-well-formed-git-dir nested1/nested2/nested3/.git &&
+ git rev-parse --is-well-formed-git-dir nested1/nested2/nested3/submodule/.git
+ )
'
test_expect_success 'test "update --recursive" with a flag with spaces' '
@@ -262,11 +265,11 @@ test_expect_success 'test "update --recursive" with a flag with spaces' '
git clone super clone5 &&
(
cd clone5 &&
- test ! -d nested1/.git &&
+ test_must_fail git rev-parse --is-well-formed-git-dir d nested1/.git &&
git submodule update --init --recursive --reference="$(dirname "$PWD")/common objects" &&
- test -d nested1/.git &&
- test -d nested1/nested2/.git &&
- test -d nested1/nested2/nested3/.git &&
+ git rev-parse --is-well-formed-git-dir nested1/.git &&
+ git rev-parse --is-well-formed-git-dir nested1/nested2/.git &&
+ git rev-parse --is-well-formed-git-dir nested1/nested2/nested3/.git &&
test -f nested1/.git/objects/info/alternates &&
test -f nested1/nested2/.git/objects/info/alternates &&
test -f nested1/nested2/nested3/.git/objects/info/alternates
@@ -277,18 +280,18 @@ test_expect_success 'use "update --recursive nested1" to checkout all submodules
git clone super clone6 &&
(
cd clone6 &&
- test ! -d sub1/.git &&
- test ! -d sub2/.git &&
- test ! -d sub3/.git &&
- test ! -d nested1/.git &&
+ test_must_fail git rev-parse --is-well-formed-git-dir sub1/.git &&
+ test_must_fail git rev-parse --is-well-formed-git-dir sub2/.git &&
+ test_must_fail git rev-parse --is-well-formed-git-dir sub3/.git &&
+ test_must_fail git rev-parse --is-well-formed-git-dir nested1/.git &&
git submodule update --init --recursive -- nested1 &&
- test ! -d sub1/.git &&
- test ! -d sub2/.git &&
- test ! -d sub3/.git &&
- test -d nested1/.git &&
- test -d nested1/nested2/.git &&
- test -d nested1/nested2/nested3/.git &&
- test -d nested1/nested2/nested3/submodule/.git
+ test_must_fail git rev-parse --is-well-formed-git-dir sub1/.git &&
+ test_must_fail git rev-parse --is-well-formed-git-dir sub2/.git &&
+ test_must_fail git rev-parse --is-well-formed-git-dir sub3/.git &&
+ git rev-parse --is-well-formed-git-dir nested1/.git &&
+ git rev-parse --is-well-formed-git-dir nested1/nested2/.git &&
+ git rev-parse --is-well-formed-git-dir nested1/nested2/nested3/.git &&
+ git rev-parse --is-well-formed-git-dir nested1/nested2/nested3/submodule/.git
)
'
--
1.7.6.403.g1fd2f.dirty
^ permalink raw reply related
* [PATCH v3 2/2] Move git-dir for submodules
From: Fredrik Gustafsson @ 2011-08-12 19:55 UTC (permalink / raw)
To: git; +Cc: iveqy, jens.lehmann, hvoigt, gitster
In-Reply-To: <1313178913-25617-1-git-send-email-iveqy@iveqy.com>
Move git-dir for submodules into $GIT_DIR/modules/[name_of_submodule] of
the superproject. This is a step towards being able to delete submodule
directories without loosing the information from their .git directory
as that is now stored outside the submodules work tree.
This is done relying on the already existent .git-file functionality.
When adding or updating a submodule whose git directory is found under
$GIT_DIR/modules/[name_of_submodule], don't clone it again but simply
point the .git-file to it and remove the now stale index file from it.
The index will be recreated by the following checkout.
This patch will not affect already cloned submodules at all.
Tests that rely on .git being a directory have been fixed.
Signed-off-by: Fredrik Gustafsson <iveqy@iveqy.com>
Mentored-by: Jens Lehmann <Jens.Lehmann@web.de>
Mentored-by: Heiko Voigt <hvoigt@hvoigt.net>
---
git-submodule.sh | 49 ++++++++++++++++--
t/t7406-submodule-update.sh | 107 ++++++++++++++++++++++++++++++++++++++++
t/t7407-submodule-foreach.sh | 6 +-
t/t7408-submodule-reference.sh | 4 +-
4 files changed, 156 insertions(+), 10 deletions(-)
diff --git a/git-submodule.sh b/git-submodule.sh
index bc1d3fa..ace6c1d 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -122,14 +122,53 @@ module_clone()
path=$1
url=$2
reference="$3"
+ gitdir=
+ gitdir_base=
+ name=$(module_name "$path")
+ if test -z "$name"
+ then
+ name="$path"
+ fi
+ base_path=$(dirname "$path")
+
+ gitdir=$(git rev-parse --git-dir)
+ gitdir_base="$gitdir/modules/$base_path"
+ gitdir="$gitdir/modules/$path"
+
+ case $gitdir in
+ /*)
+ a="$(cd_to_toplevel && pwd)/"
+ b=$gitdir
+ while [ "$b" ] && [ "${a%%/*}" = "${b%%/*}" ]
+ do
+ a=${a#*/} b=${b#*/};
+ done
+
+ rel="$a$name"
+ rel=`echo $rel | sed -e 's|[^/]*|..|g'`
+ rel_gitdir="$rel/$b"
+ ;;
+ *)
+ rel=`echo $name | sed -e 's|[^/]*|..|g'`
+ rel_gitdir="$rel/$gitdir"
+ ;;
+ esac
- if test -n "$reference"
+ if test -d "$gitdir"
then
- git-clone "$reference" -n "$url" "$path"
+ mkdir -p "$path"
+ echo "gitdir: $rel_gitdir" >"$path/.git"
+ rm -f "$gitdir/index"
else
- git-clone -n "$url" "$path"
- fi ||
- die "$(eval_gettext "Clone of '\$url' into submodule path '\$path' failed")"
+ mkdir -p "$gitdir_base"
+ if test -n "$reference"
+ then
+ git-clone "$reference" -n "$url" "$path" --separate-git-dir "$gitdir"
+ else
+ git-clone -n "$url" "$path" --separate-git-dir "$gitdir"
+ fi ||
+ die "$(eval_gettext "Clone of '\$url' into submodule path '\$path' failed")"
+ fi
}
#
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index c679f36..1ae6b4e 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -408,6 +408,7 @@ test_expect_success 'submodule update exit immediately in case of merge conflict
test_cmp expect actual
)
'
+
test_expect_success 'submodule update exit immediately after recursive rebase error' '
(cd super &&
git checkout master &&
@@ -442,4 +443,110 @@ test_expect_success 'submodule update exit immediately after recursive rebase er
test_cmp expect actual
)
'
+
+test_expect_success 'add different submodules to the same path' '
+ (cd super &&
+ git submodule add ../submodule s1 &&
+ test_must_fail git submodule add ../merging s1
+ )
+'
+
+test_expect_success 'submodule add places git-dir in superprojects git-dir' '
+ (cd super &&
+ mkdir deeper &&
+ git submodule add ../submodule deeper/submodule &&
+ (cd deeper/submodule &&
+ git log > ../../expected
+ ) &&
+ (cd .git/modules/deeper/submodule &&
+ git log > ../../../../actual
+ ) &&
+ test_cmp actual expected
+ )
+'
+
+test_expect_success 'submodule update places git-dir in superprojects git-dir' '
+ (cd super &&
+ git commit -m "added submodule"
+ ) &&
+ git clone super super2 &&
+ (cd super2 &&
+ git submodule init deeper/submodule &&
+ git submodule update &&
+ (cd deeper/submodule &&
+ git log > ../../expected
+ ) &&
+ (cd .git/modules/deeper/submodule &&
+ git log > ../../../../actual
+ ) &&
+ test_cmp actual expected
+ )
+'
+
+test_expect_success 'submodule add places git-dir in superprojects git-dir recursive' '
+ (cd super2 &&
+ (cd deeper/submodule &&
+ git submodule add ../submodule subsubmodule &&
+ (cd subsubmodule &&
+ git log > ../../../expected
+ ) &&
+ git commit -m "added subsubmodule" &&
+ git push
+ ) &&
+ (cd .git/modules/deeper/submodule/modules/subsubmodule &&
+ git log > ../../../../../actual
+ ) &&
+ git add deeper/submodule &&
+ git commit -m "update submodule" &&
+ git push &&
+ test_cmp actual expected
+ )
+'
+
+test_expect_success 'submodule update places git-dir in superprojects git-dir recursive' '
+ mkdir super_update_r &&
+ (cd super_update_r &&
+ git init --bare
+ ) &&
+ mkdir subsuper_update_r &&
+ (cd subsuper_update_r &&
+ git init --bare
+ ) &&
+ mkdir subsubsuper_update_r &&
+ (cd subsubsuper_update_r &&
+ git init --bare
+ ) &&
+ git clone subsubsuper_update_r subsubsuper_update_r2 &&
+ (cd subsubsuper_update_r2 &&
+ test_commit "update_subsubsuper" file &&
+ git push origin master
+ ) &&
+ git clone subsuper_update_r subsuper_update_r2 &&
+ (cd subsuper_update_r2 &&
+ test_commit "update_subsuper" file &&
+ git submodule add ../subsubsuper_update_r subsubmodule &&
+ git commit -am "subsubmodule" &&
+ git push origin master
+ ) &&
+ git clone super_update_r super_update_r2 &&
+ (cd super_update_r2 &&
+ test_commit "update_super" file &&
+ git submodule add ../subsuper_update_r submodule &&
+ git commit -am "submodule" &&
+ git push origin master
+ ) &&
+ rm -rf super_update_r2 &&
+ git clone super_update_r super_update_r2 &&
+ (cd super_update_r2 &&
+ git submodule update --init --recursive &&
+ (cd submodule/subsubmodule &&
+ git log > ../../expected
+ ) &&
+ (cd .git/modules/submodule/modules/subsubmodule
+ git log > ../../../../../actual
+ )
+ test_cmp actual expected
+ )
+'
+
test_done
diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh
index 1a974e2..e410bd4 100755
--- a/t/t7407-submodule-foreach.sh
+++ b/t/t7407-submodule-foreach.sh
@@ -270,9 +270,9 @@ test_expect_success 'test "update --recursive" with a flag with spaces' '
git rev-parse --is-well-formed-git-dir nested1/.git &&
git rev-parse --is-well-formed-git-dir nested1/nested2/.git &&
git rev-parse --is-well-formed-git-dir nested1/nested2/nested3/.git &&
- test -f nested1/.git/objects/info/alternates &&
- test -f nested1/nested2/.git/objects/info/alternates &&
- test -f nested1/nested2/nested3/.git/objects/info/alternates
+ test -f .git/modules/nested1/objects/info/alternates &&
+ test -f .git/modules/nested1/modules/nested2/objects/info/alternates &&
+ test -f .git/modules/nested1/modules/nested2/modules/nested3/objects/info/alternates
)
'
diff --git a/t/t7408-submodule-reference.sh b/t/t7408-submodule-reference.sh
index cc16d3f..ab37c36 100755
--- a/t/t7408-submodule-reference.sh
+++ b/t/t7408-submodule-reference.sh
@@ -43,7 +43,7 @@ git commit -m B-super-added'
cd "$base_dir"
test_expect_success 'after add: existence of info/alternates' \
-'test `wc -l <super/sub/.git/objects/info/alternates` = 1'
+'test `wc -l <super/.git/modules/sub/objects/info/alternates` = 1'
cd "$base_dir"
@@ -66,7 +66,7 @@ test_expect_success 'update with reference' \
cd "$base_dir"
test_expect_success 'after update: existence of info/alternates' \
-'test `wc -l <super-clone/sub/.git/objects/info/alternates` = 1'
+'test `wc -l <super-clone/.git/modules/sub/objects/info/alternates` = 1'
cd "$base_dir"
--
1.7.6.403.g1fd2f.dirty
^ permalink raw reply related
* [PATCH v3 0/2] submodule: move gitdir into superproject
From: Fredrik Gustafsson @ 2011-08-12 19:55 UTC (permalink / raw)
To: git; +Cc: iveqy, jens.lehmann, hvoigt, gitster
Move git-dir for submodules into $GIT_DIR/modules/[name_of_submodule] of
the superproject. This is a step towards being able to delete submodule
directories without loosing the information from their .git directory
as that is now stored outside the submodules work tree.
This is done relying on the already existent .git-file functionality.
Tests that rely on .git being a directory have been fixed.
This is the third iteration of this patchseries. In this iteration the
commit message of the second patch is updated and the fixup-patch from
Junio squashed with the first commit.
The first can be found here:
http://thread.gmane.org/gmane.comp.version-control.git/177582
The second can be found here:
http://thread.gmane.org/gmane.comp.version-control.git/178970/focus=179154
Fredrik Gustafsson (2):
rev-parse: add option --is-well-formed-git-dir [path]
Move git-dir for submodules
Documentation/git-rev-parse.txt | 4 ++
builtin/rev-parse.c | 8 +++
cache.h | 1 +
git-submodule.sh | 49 ++++++++++++++++--
setup.c | 7 +++
t/t7400-submodule-basic.sh | 4 +-
t/t7403-submodule-sync.sh | 5 +-
t/t7406-submodule-update.sh | 107 +++++++++++++++++++++++++++++++++++++++
t/t7407-submodule-foreach.sh | 103 +++++++++++++++++++------------------
t/t7408-submodule-reference.sh | 4 +-
10 files changed, 231 insertions(+), 61 deletions(-)
--
1.7.6.403.g1fd2f.dirty
^ permalink raw reply
* Re: Overriding ~/.gitconfig using GIT_CONFIG
From: Junio C Hamano @ 2011-08-12 19:39 UTC (permalink / raw)
To: Richard Purdie, Daniel Barkalow
Cc: Nguyễn Thái Ngọc Duy, GIT Mailing-list
In-Reply-To: <7vr54qmodf.fsf@alter.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> writes:
> Richard Purdie <rpurdie@rpsys.net> writes:
>
>> Looking through the manuals/code, it suggests I should be able to do:
>>
>> GIT_CONFIG=/dev/null git XXX
>>
>> and all should work happily. It doesn't though. As an example, with a
>> ~/.gitconfig, "GIT_CONFIG=/dev/null git fetch --all" is clearly
>> accessing the file in ~ and then acting upon it.
>
> If the manual says the above is expected for any value of XXX, then that
> is a bug in the manual since mid 2008, I think.
>
> See dc87183 (Only use GIT_CONFIG in "git config", not other programs,
> 2008-06-30).
>
> I _think_ these days a workaround to force a known config is to set HOME
> to a value that has a known .gitconfig (or no such file), and decline
> usage of /etc/git.config by exporting GIT_CONFIG_NOSYSTEM.
Side note. Here is what dc87183 says:
commit dc87183189b54441e315d35d48983d80ab085299
Author: Daniel Barkalow <barkalow@iabervon.org>
Date: Mon Jun 30 03:37:47 2008 -0400
Only use GIT_CONFIG in "git config", not other programs
For everything other than using "git config" to read or write a
git-style config file that isn't the current repo's config file,
GIT_CONFIG was actively detrimental. Rather than argue over which
programs are important enough to have work anyway, just fix all of
them at the root.
Also removes GIT_LOCAL_CONFIG, which would only be useful for programs
that do want to use global git-specific config, but not the repo's own
git-specific config, and want to use some other, presumably
git-specific config. Despite being documented, I can't find any sign that
it was ever used.
Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
It clearly explains the reason why LOCAL_CONFIG was removed (the reader
does not have to agree with "I can't find any sign that it was ever used",
though), but I cannot read from the first paragraph the reason why it was
felt necessary not to honor GIT_CONFIG in other programs, i.e. "was
actively detrimental" is not backed by any example in the paragraph. I can
sort of sense from "Rather than argue over..." that there may have been a
discussion on the list, and reading the archive from that timeframe may
reveal why many felt it was not a good idea.
Daniel, do you recall the context?
^ permalink raw reply
* Re: Overriding ~/.gitconfig using GIT_CONFIG
From: Junio C Hamano @ 2011-08-12 19:16 UTC (permalink / raw)
To: Richard Purdie
Cc: Daniel Barkalow, Nguyễn Thái Ngọc Duy,
GIT Mailing-list
In-Reply-To: <1313163498.14274.505.camel@rex>
Richard Purdie <rpurdie@rpsys.net> writes:
> Looking through the manuals/code, it suggests I should be able to do:
>
> GIT_CONFIG=/dev/null git XXX
>
> and all should work happily. It doesn't though. As an example, with a
> ~/.gitconfig, "GIT_CONFIG=/dev/null git fetch --all" is clearly
> accessing the file in ~ and then acting upon it.
If the manual says the above is expected for any value of XXX, then that
is a bug in the manual since mid 2008, I think.
See dc87183 (Only use GIT_CONFIG in "git config", not other programs,
2008-06-30).
I _think_ these days a workaround to force a known config is to set HOME
to a value that has a known .gitconfig (or no such file), and decline
usage of /etc/git.config by exporting GIT_CONFIG_NOSYSTEM.
^ permalink raw reply
* Re: git ls-files --error-unmatch weirdness
From: Junio C Hamano @ 2011-08-12 17:56 UTC (permalink / raw)
To: SZEDER Gábor; +Cc: git
In-Reply-To: <20110812132436.GA12147@goldbirke>
SZEDER Gábor <szeder@ira.uka.de> writes:
> repo (master)$ git ls-files --others --error-unmatch
The "--error-unmatch" is about reporting errors in pathspecs you gave from
the command line. The behaviour is undefined if you do not give any, like
the above command line.
Having said that, I wouldn't be surprised if it triggered when run from an
empty subdirectory.
^ 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