Git development
 help / color / mirror / Atom feed
* Re: [Census] So who uses git?
From: Carl Baldwin @ 2006-01-31 15:24 UTC (permalink / raw)
  To: Johannes Schindelin
  Cc: Junio C Hamano, Keith Packard, Martin Langhoff, Linus Torvalds,
	Git Mailing List
In-Reply-To: <Pine.LNX.4.63.0601311127250.25248@wbgn013.biozentrum.uni-wuerzburg.de>

Its difficult to explain because it breaks away from the precedent set
by other SCMs.  I wouldn't call it a show-stopper for this reason.  In
fact, some who have wrapped their heads around the concept might call it
a valuable feature.  I, myself, have found it a handy thing in certain
circumstances.  In other circumstances I simply bypass it by adding -a
to the command-line.

This doesn't fit my definition of a show-stopper.

Carl

On Tue, Jan 31, 2006 at 11:27:34AM +0100, Johannes Schindelin wrote:
> Hi,
> 
> On Mon, 30 Jan 2006, Carl Baldwin wrote:
> 
> > In general, I think it is grasping the reason for the index file and how 
> > git commands like git-commit and git-diff interact with it.
> 
> IMHO this is the one big showstopper. I had problems explaining the 
> concept myself.
> 
> For example, I had a hard time explaining to a friend why a git-add'ed 
> file is committed when saying "git commit some_other_file", but not 
> another (modified) file. Very unintuitive.
> 
> Ciao,
> Dscho
> 
> 

-- 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 Carl Baldwin                        RADCAD (R&D CAD)
 Hewlett Packard Company
 MS 88                               work: 970 898-1523
 3404 E. Harmony Rd.                 work: Carl.N.Baldwin@hp.com
 Fort Collins, CO 80525              home: Carl@ecBaldwin.net
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

^ permalink raw reply

* Re: [RFC] shallow clone
From: Simon Richter @ 2006-01-31 14:23 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Junio C Hamano, git
In-Reply-To: <Pine.LNX.4.63.0601311422400.7918@wbgn013.biozentrum.uni-wuerzburg.de>

[-- Attachment #1: Type: text/plain, Size: 607 bytes --]

Hi,

Johannes Schindelin wrote:

> If you pull, upload-pack will think you have *every* object depending on 
> every ref you have stored.

Ah, okay. That was the missing information, thanks.

> You only have two choices: you proposed code duplication, and yours truly 
> proposed data duplication.

Erm, if there are multiple places for parsing a grafts file, that needs 
to be addressed as well.

> As is known from good database design: a few redundancies here and there 
> are typically needed for good performance.

Sure, but only if you can "rebuild" all the redundant information reliably.

    Simon

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 307 bytes --]

^ permalink raw reply

* Re: [RFC] shallow clone
From: Johannes Schindelin @ 2006-01-31 14:20 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7v8xsxa70o.fsf@assigned-by-dhcp.cox.net>

Hi,

On Mon, 30 Jan 2006, Junio C Hamano wrote:

> We need to realize that `upload-pack` that hears
> "have A, want B" is allowed to omit objects that appear in
> `ls-tree B` output but not in `ls-tree A`.  "have A" means not
> just "I have A", but "I have A and all of its ancestors", so
> just sending "have start_shallow" (or start_shallow^ for that
> matter) is not quite enough.

So how about adding a "have-single A" which would be translated to 
"git-rev-list ~A", which in turn would only mark the tree and its 
children, but not the parents?

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH] Shallow clone: low level machinery.
From: Johannes Schindelin @ 2006-01-31 13:58 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vmzhc1wz6.fsf_-_@assigned-by-dhcp.cox.net>

Hi,

apart from my thinking this is not backward-compatible (you are supposed 
to be able to pull from a complete repo, even if it has a 
non-shallow-capable upload-pack), here are my comments:

- it is good that MAXPARENT and struct commit_graft are in more public 
	places now.

- reparse_* is misleading. Nothing is reparsed, but rather "unparsed".

- I'd hesitate to let git-daemon write temporary files. That is a whole 
	new can of security worms.

- It looks wrong to me to define MAX_PARENTS as 20 in upload-pack.c, when 
	MAXPARENT is defined as 16 in cache.h.

- The custom_graft issue could be handled in a more elegant manner if 
	git was lib'ified (no temporary file). Since that is already the 
	plan, why not do that first, and come back later?

Ciao,
Dscho

^ permalink raw reply

* Re: [RFC] shallow clone
From: Johannes Schindelin @ 2006-01-31 13:31 UTC (permalink / raw)
  To: Simon Richter; +Cc: Junio C Hamano, git
In-Reply-To: <43DF608C.1060201@hogyros.de>

Hi,

On Tue, 31 Jan 2006, Simon Richter wrote:

> Well, the important thing would be that commands that can work (a merge only
> needs to find the most recent common ancestor, etc) do work, and commands that
> cannot ("log") emit sensible diagnostics.

No it would not.

A commit is a very small object which points (among others) to a tree 
object.

A tree object corresponds to a directory (that is, it can point to a 
number of tree and blob objects).

A blob object corresponds to a file (that is, git never parses its 
contents).

If two separate revisions contain the same file (i.e. same contents), this 
is not duplicated, but the corresponding tree objects point to the same 
object.

If you pull, upload-pack will think you have *every* object depending on 
every ref you have stored.

Say you have three revisions, A -> B -> C, and A and C contain the 
same file bla.txt, and the client says it has B, the upstream upload-pack 
assumes you have bla.txt.

> I know far too little about the internal workings for that, [...]

I hope I clarified the important aspect.

> > If you now rely on the grafts file to determine what was a cutoff, you may
> > well end up with bogus cutoffs.
> 
> Exactly that was my concern earlier; my database design gut feeling tells me
> that information duplication is not good either, [...]

You only have two choices: you proposed code duplication, and yours truly 
proposed data duplication.

As is known from good database design: a few redundancies here and there 
are typically needed for good performance.

Ciao,
Dscho

^ permalink raw reply

* Idea: "repair" tool
From: Simon Richter @ 2006-01-31 13:16 UTC (permalink / raw)
  To: git

[-- Attachment #1: Type: text/plain, Size: 473 bytes --]

Hi,

since one of my linux-2.6 repos got damaged by filesystem corruption (a 
bunch of objects vanished), I am wondering whether it would make sense 
to have a small tool that would get a list of missing objects and try to 
acquire them from all known remote repos (possibly with the approach of 
trying the one you got the last object from first, as usually only files 
from the same pull will have problems if there are filesystem issues).

What do you think?

    Simon

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 307 bytes --]

^ permalink raw reply

* Re: [RFC] shallow clone
From: Simon Richter @ 2006-01-31 13:05 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Junio C Hamano, git
In-Reply-To: <Pine.LNX.4.63.0601311127490.25248@wbgn013.biozentrum.uni-wuerzburg.de>

[-- Attachment #1: Type: text/plain, Size: 2733 bytes --]

Hi,

Johannes Schindelin wrote:

>>If the downstream person wants to have a shallow history of post
>>X.org X server core to further hack on it, I do not think of a
>>reason why we would want to refuse her from cloning a repository
>>of a fellow developer who has already done such a shallow copy.

> Okay. But in their case, they'll probably do what was done with Linux: 
> start afresh. If you want to have the old history, you can import it and 
> merge it via a graft.

Well, in the Linux case the problem was not knowing what the SHA1 sum of 
the entire Linux history was. In the shallow repo case we know it, so 
there is no point in throwing away that information.

>>If such a clone is done without telling the downstream that the
>>result is a shallow one, it is "dumb".  I would agree it should
>>not be done.

> That was my point. As long as you don't make sure the client handles the 
> shallow upstream gracefully, it is dangerous. At the moment, there are too 
> many code parts relying on the completeness of the repository (local and 
> remote).

Well, the important thing would be that commands that can work (a merge 
only needs to find the most recent common ancestor, etc) do work, and 
commands that cannot ("log") emit sensible diagnostics.

> Just imagine this: Alice starts a project, Bob makes a shallow copy from 
> it when Alice just reverted an experimental feature. Then, Alice decides 
> the experimental feature was not bad at all and reverts the revert. Bob 
> pulls from Alice: Alice's upload-pack assumes Bob already has the original 
> files (now re-reverted), and Bob ends up with a broken repository.

I know far too little about the internal workings for that, but I'd 
assume that in this case Bob's copy starts at the commit that was never 
in question (and he never saw the reverted commit), and Alice's contains 
a commit on top of that. That one should work. But the other way 'round 
is problematic, when Bob starts with a commit that has been reverted in 
Alice's repository. The solution is for Bob to ask Alice's repo for the 
common ancestor of his shallow base and Alice's HEAD. Alice's repo can, 
however, fail to deliver these if there has been a purge since, in that 
case, stuff needs to be merged by hand (but you already have a problem 
if someone clones your repo before you revert changes, so no regression 
here).

> If you now rely on the grafts file to determine what was a cutoff, you may 
> well end up with bogus cutoffs.

Exactly that was my concern earlier; my database design gut feeling 
tells me that information duplication is not good either, hence my 
suggestion to split off these grafts into a separate file in order to 
mark them as cutoff points.

    Simon

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 307 bytes --]

^ permalink raw reply

* Re: git-http-fetch failure/segfault -- alas no patch
From: Mark Wooding @ 2006-01-31 11:46 UTC (permalink / raw)
  To: Uwe Zeisberger; +Cc: git
In-Reply-To: <20060131093200.GA5154@informatik.uni-freiburg.de>

Uwe Zeisberger <zeisberg@informatik.uni-freiburg.de> wrote:

> The offending commit is 056211053b7516a57ff7a6dd02f503ecef6fca70:
> 
> git-clone: do not special case dumb http.

Fine, except that it's quite clear to me that the bug is actually in
git-http-fetch -- it shouldn't segfault, dammit! -- and that commit
affects only git-clone.sh.  Besides, I get the same symptoms running
git-http-fetch by hand.  That commit appears if you bisect on a test
based on git-clone because before then it fetched the pack list and pack
files before it tried to mop up the remaining objects, which obviously
hides the underlying bug.

Here's my low-level test-case.

----
#! /bin/sh

set -e
rm -rf funt
GIT_DIR=funt; export GIT_DIR
./git-init-db
./git-http-fetch -a -v \
  heads/master http://boyle.nsict.org/~mdw/git/catacomb.broken/
----

This is the `real-life' repository which has broken.  I'm using it
because the patch I made /works/ on the trivial `funt' example, but
fails miserably on the real thing.

Bisecting with this test lays the blame on 1d389ab65dc6867d30...  Which
I think is just telling me that it's always been broken.

For amusement value, my patch is below.  Here's what happens if I try to
use it.

----
got 7c40480318648672af86e03bc72bc45c07194c37
walk 7c40480318648672af86e03bc72bc45c07194c37
Getting alternates list for
http://boyle.nsict.org/~mdw/git/catacomb.broken/
got 0fd8bd4823315feb1c537a154efba002c053ed8e
Getting pack list for http://boyle.nsict.org/~mdw/git/catacomb.broken/
Getting index for pack f6d543b58ba9183c53ddbd981835f0378bdab919
Getting pack f6d543b58ba9183c53ddbd981835f0378bdab919
 which contains a137c6b3695c32ea9c42520a387a85641687662f
walk a137c6b3695c32ea9c42520a387a85641687662f
error: fd leakage in release: 4
error: fd leakage in release: 9
error: fd leakage in release: 5
error: fd leakage in release: 7
got 53124000638e53ee8aa51830fab72d8a0ce654e4
error: Couldn't find request for d2f2768351d41f80469240d1b533575d833c7370 in the queue
error: Unable to find d2f2768351d41f80469240d1b533575d833c7370 under http://boyle.nsict.org/~mdw/git/catacomb.broken/

Cannot obtain needed blob d2f2768351d41f80469240d1b533575d833c7370
while processing commit a137c6b3695c32ea9c42520a387a85641687662f.
Waiting for
http://boyle.nsict.org/~mdw/git/catacomb.broken/objects/eb/2dc153b8981ad02430bc166b925ef2457c7c36
got eb2dc153b8981ad02430bc166b925ef2457c7c36
Segmentation fault      (core dumped)
----

Without the patch, I get

----
got 7c40480318648672af86e03bc72bc45c07194c37
walk 7c40480318648672af86e03bc72bc45c07194c37
Getting alternates list for
http://boyle.nsict.org/~mdw/git/catacomb.broken/
got 0fd8bd4823315feb1c537a154efba002c053ed8e
Getting pack list for http://boyle.nsict.org/~mdw/git/catacomb.broken/
got 53124000638e53ee8aa51830fab72d8a0ce654e4
got eb2dc153b8981ad02430bc166b925ef2457c7c36
error: Unable to find a137c6b3695c32ea9c42520a387a85641687662f under http://boyle.nsict.org/~mdw/git/catacomb.broken/
----

And the patch itself.  Warning!  This DOES NOT WORK!  (But it may be of
some use to you lot anyway.)

git-http-fetch: Fix failure to find pack list.

From:  <mdw@distorted.org.uk>

  * Problem seems to be premature reuse of a slot.  In some cases, we
    end up fetching the exit status for a different fetch; if that fetch
    fails (because the object is already in a pack) then the pack list
    fetch is assumed to fail and the entire fetch falls apart.
---

 http.c   |   49 +++++++++++++++++++++++++++++++++++++++----------
 http.h   |    8 +++++++-
 2 files changed, 46 insertions(+), 11 deletions(-)

diff --git a/http.c b/http.c
index 75e6717..54aa9ee 100644
--- a/http.c
+++ b/http.c
@@ -1,3 +1,4 @@
+#include <assert.h>
 #include "http.h"
 
 int data_received;
@@ -192,6 +193,9 @@ static CURL* get_curl_handle(void)
 
 	curl_easy_setopt(result, CURLOPT_FOLLOWLOCATION, 1);
 
+	if (getenv("GIT_CURL_VERBOSE"))
+		curl_easy_setopt(result, CURLOPT_VERBOSE, 1);
+
 	return result;
 }
 
@@ -262,7 +266,7 @@ void http_cleanup(void)
 
 	while (slot != NULL) {
 #ifdef USE_CURL_MULTI
-		if (slot->in_use) {
+		if (slot->in_use & SLOTUSE_ACTIVE) {
 			curl_easy_getinfo(slot->curl,
 					  CURLINFO_EFFECTIVE_URL,
 					  &wait_url);
@@ -311,6 +315,7 @@ struct active_request_slot *get_active_s
 		newslot->curl = NULL;
 		newslot->in_use = 0;
 		newslot->next = NULL;
+		newslot->nrefs = 0;
 
 		slot = active_queue_head;
 		if (slot == NULL) {
@@ -333,7 +338,7 @@ struct active_request_slot *get_active_s
 	}
 
 	active_requests++;
-	slot->in_use = 1;
+	slot->in_use |= SLOTUSE_ACTIVE;
 	slot->local = NULL;
 	slot->callback_data = NULL;
 	slot->callback_func = NULL;
@@ -351,8 +356,9 @@ int start_active_slot(struct active_requ
 
 	if (curlm_result != CURLM_OK &&
 	    curlm_result != CURLM_CALL_MULTI_PERFORM) {
-		active_requests--;
-		slot->in_use = 0;
+		slot->in_use &= ~SLOTUSE_ACTIVE;
+		if (!slot->in_use)
+			active_requests--;
 		return 0;
 	}
 #endif
@@ -375,6 +381,25 @@ void step_active_slots(void)
 }
 #endif
 
+void watch_active_slot(struct active_request_slot *slot)
+{
+	if (!slot->in_use)
+		active_requests++;
+	slot->in_use |= SLOTUSE_REF;
+	slot->nrefs++;
+}
+
+void unwatch_active_slot(struct active_request_slot *slot)
+{
+	assert(slot->nrefs);
+	slot->nrefs--;
+	if (!slot->nrefs) {
+		slot->in_use &= ~SLOTUSE_REF;
+		if (!slot->in_use)
+			active_requests--;
+	}
+}
+
 void run_active_slot(struct active_request_slot *slot)
 {
 #ifdef USE_CURL_MULTI
@@ -386,7 +411,8 @@ void run_active_slot(struct active_reque
 	int max_fd;
 	struct timeval select_timeout;
 
-	while (slot->in_use) {
+	watch_active_slot(slot);
+	while (slot->in_use & SLOTUSE_ACTIVE) {
 		data_received = 0;
 		step_active_slots();
 
@@ -397,7 +423,7 @@ void run_active_slot(struct active_reque
 			last_pos = current_pos;
 		}
 
-		if (slot->in_use && !data_received) {
+		if ((slot->in_use & SLOTUSE_ACTIVE) && !data_received) {
 			max_fd = 0;
 			FD_ZERO(&readfds);
 			FD_ZERO(&writefds);
@@ -408,8 +434,9 @@ void run_active_slot(struct active_reque
 			       &excfds, &select_timeout);
 		}
 	}
+	unwatch_active_slot(slot);
 #else
-	while (slot->in_use) {
+	while (slot->in_use & SLOTUSE_ACTIVE) {
 		slot->curl_result = curl_easy_perform(slot->curl);
 		finish_active_slot(slot);
 	}
@@ -418,8 +445,10 @@ void run_active_slot(struct active_reque
 
 static void finish_active_slot(struct active_request_slot *slot)
 {
-        active_requests--;
-        slot->in_use = 0;
+	assert(slot->in_use & SLOTUSE_ACTIVE);
+        slot->in_use &= ~SLOTUSE_ACTIVE;
+	if (!slot->in_use)
+		active_requests--;
         curl_easy_getinfo(slot->curl, CURLINFO_HTTP_CODE, &slot->http_code);
  
         /* Run callback if appropriate */
@@ -433,7 +462,7 @@ void finish_all_active_slots(void)
 	struct active_request_slot *slot = active_queue_head;
 
 	while (slot != NULL)
-		if (slot->in_use) {
+		if (slot->in_use & SLOTUSE_ACTIVE) {
 			run_active_slot(slot);
 			slot = active_queue_head;
 		} else {
diff --git a/http.h b/http.h
index ed4ea33..6913c6a 100644
--- a/http.h
+++ b/http.h
@@ -26,7 +26,8 @@ struct active_request_slot
 {
 	CURL *curl;
 	FILE *local;
-	int in_use;
+	unsigned in_use;
+	int nrefs;
 	CURLcode curl_result;
 	long http_code;
 	void *callback_data;
@@ -34,6 +35,9 @@ struct active_request_slot
 	struct active_request_slot *next;
 };
 
+#define SLOTUSE_ACTIVE 1u
+#define SLOTUSE_REF 2u
+
 struct buffer
 {
         size_t posn;
@@ -54,6 +58,8 @@ extern struct active_request_slot *get_a
 extern int start_active_slot(struct active_request_slot *slot);
 extern void run_active_slot(struct active_request_slot *slot);
 extern void finish_all_active_slots(void);
+extern void watch_active_slot(struct active_request_slot *slot);
+extern void unwatch_active_slot(struct active_request_slot *slot);
 
 #ifdef USE_CURL_MULTI
 extern void fill_active_slots(void);

-- [mdw]

^ permalink raw reply related

* Re: [RFC] shallow clone
From: Johannes Schindelin @ 2006-01-31 11:28 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vzmld7c2g.fsf@assigned-by-dhcp.cox.net>

Hi,

On Mon, 30 Jan 2006, Junio C Hamano wrote:

> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> 
> >> > - disallow fetching from this repo, and
> >> 
> >> Why? It's perfectly acceptable to pull from an incomplete
> >> repo, as long as you don't care about the old history.
> >
> > Right. But should that be the default? I don't think so. Therefore: 
> > disable it, and if the user is absolutely sure to do dumb things, she'll 
> > have to enable it explicitely.
> 
> If the downstream person wants to have a shallow history of post
> X.org X server core to further hack on it, I do not think of a
> reason why we would want to refuse her from cloning a repository
> of a fellow developer who has already done such a shallow copy.

Okay. But in their case, they'll probably do what was done with Linux: 
start afresh. If you want to have the old history, you can import it and 
merge it via a graft.

> If such a clone is done without telling the downstream that the
> result is a shallow one, it is "dumb".  I would agree it should
> not be done.

That was my point. As long as you don't make sure the client handles the 
shallow upstream gracefully, it is dangerous. At the moment, there are too 
many code parts relying on the completeness of the repository (local and 
remote).

Since I wrote this, I realized that the problem I saw is not limited to 
shallow upstream, but there is a subtle issue with shallow downstreams, 
too:

Just imagine this: Alice starts a project, Bob makes a shallow copy from 
it when Alice just reverted an experimental feature. Then, Alice decides 
the experimental feature was not bad at all and reverts the revert. Bob 
pulls from Alice: Alice's upload-pack assumes Bob already has the original 
files (now re-reverted), and Bob ends up with a broken repository.

While writing the last paragraph, it became clear to me that the shallow 
thing is very fragile: IMHO it is impossible to be fully backwards 
compatible (remember: you should not force anybody to upgrade).

> By the way, please refrain from discussing .git/config vs 
> .git/eparate-config-files issue in this thread.

Okay. I will shut up on that issue.

> My personal feeling so far is that the information current graft 
> represents is good enough to support shallow clones, and if not we can 
> extend its semantics to support such.

No. The grafts are more powerful. I have quite a few repos here in which I 
heavily work with grafts, and they are no cutoffs for shallow repos. They 
are hard links between different lines of development. For example, I use 
them to map merges in cvsimported projects, thus fixing a shortcoming of 
CVS. Also, you can "add" history.

If you now rely on the grafts file to determine what was a cutoff, you may 
well end up with bogus cutoffs.

Ciao,
Dscho

^ permalink raw reply

* Re: [RFC] shallow clone
From: Franck @ 2006-01-31 11:11 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vvew03hls.fsf@assigned-by-dhcp.cox.net>

2006/1/31, Junio C Hamano <junkio@cox.net>:
> Franck <vagabon.xyz@gmail.com> writes:
>
> > I built my public repository from a cautorized one and everybody who
> > is pulling from mine is aware of the lack of the full history but they
> > actually don't care. If someone is pulling from my repo, he actually
> > wants to work on my project which do not need any old thing...
>
> Mind writing up a howto on the topic?

ok I'll try to sum-up something this week, hope my bad english will be
understandable...

>
>  - How things are set up using the current tool.
>  - How others initially clone from you.
>  - How others update (pull) from you.
>  - What are the pitfalls you and others need to avoid
>    (i.e. operations that involve old history)

actually I just discovered one thanks to your first email for this
thread about reverted commit...So I'm not very the one for this
section...

>
> I brought this up, because lack of official support of shallow
> cloning was cited as one of the showstopper for a project that
> once considered switching to git but didn't, from a mailing list
> research.

again I wasn't aware that this feature is really needed...

thanks
--
               Franck

^ permalink raw reply

* [PATCH] Shallow clone: low level machinery.
From: Junio C Hamano @ 2006-01-31 11:02 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git
In-Reply-To: <7v8xsxa70o.fsf@assigned-by-dhcp.cox.net>

This adds --shallow=refname option to git-clone-pack, and
extends upload-pack protocol with "shallow" extension.

An example:

	$ mkdir junk && cd junk && git init-db
	$ git clone-pack --shallow=refs/heads/master ../git.git master

This creates a very shallow clone of my repository.  It says
"pretend refs/heads/master commit is the beginning of time, and
clone your master branch".  As before, clone-pack with explicit
head name outputs the commit object name and refname to the
standard output instead of creating the branch.  The command
creates a .git/info/grafts file to cauterize the history at that
commit as well.

I think upload-pack side is more or less ready to be debugged,
but the client side is highly experimental.  It has quite
serious limitations and is more of a proof of correctness at the
protocol extension level than for practical use:

 - Currently it can take only one ---shallow option.

 - It has to be spelled in full (refs/heads/master, not
   "master").

 - It has to be included as part of explicit refname list.

 - There is no matching --shallow in git-fetch-pack.

Signed-off-by: Junio C Hamano <junkio@cox.net>

---

 cache.h       |    9 +++
 clone-pack.c  |   69 ++++++++++++++++++++++-
 commit-tree.c |    5 --
 commit.c      |  174 +++++++++++++++++++++++++++++++++++++++------------------
 commit.h      |   14 +++++
 connect.c     |   24 ++++++++
 object.c      |    7 ++
 object.h      |    2 +
 upload-pack.c |   94 +++++++++++++++++++++++++++++--
 9 files changed, 331 insertions(+), 67 deletions(-)

75f1f4871277f403991c771eb642bdbd6fe82021
diff --git a/cache.h b/cache.h
index bdbe2d6..18d4cdb 100644
--- a/cache.h
+++ b/cache.h
@@ -111,11 +111,18 @@ static inline unsigned int create_ce_mod
 extern struct cache_entry **active_cache;
 extern unsigned int active_nr, active_alloc, active_cache_changed;
 
+/*
+ * Having more than two parents is not strange at all, and this is
+ * how multi-way merges are represented.
+ */
+#define MAXPARENT (16)
+
 #define GIT_DIR_ENVIRONMENT "GIT_DIR"
 #define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
 #define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
 #define INDEX_ENVIRONMENT "GIT_INDEX_FILE"
 #define GRAFT_ENVIRONMENT "GIT_GRAFT_FILE"
+#define GRAFT_INFO_ENVIRONMENT "GIT_GRAFT_INFO"
 
 extern char *get_git_dir(void);
 extern char *get_object_directory(void);
@@ -296,6 +303,8 @@ struct ref {
 	char name[FLEX_ARRAY]; /* more */
 };
 
+extern void send_graft_info(int);
+
 extern int git_connect(int fd[2], char *url, const char *prog);
 extern int finish_connect(pid_t pid);
 extern int path_match(const char *path, int nr, char **match);
diff --git a/clone-pack.c b/clone-pack.c
index f634431..c1708d5 100644
--- a/clone-pack.c
+++ b/clone-pack.c
@@ -1,15 +1,76 @@
 #include "cache.h"
 #include "refs.h"
 #include "pkt-line.h"
+#include "commit.h"
 
 static const char clone_pack_usage[] =
-"git-clone-pack [--exec=<git-upload-pack>] [<host>:]<directory> [<heads>]*";
+"git-clone-pack [--shallow=name] [--exec=<git-upload-pack>] [<host>:]<directory> [<heads>]*";
 static const char *exec = "git-upload-pack";
+static char *shallow = NULL;
+
+static void shallow_exchange(int fd[2], struct ref *ref)
+{
+	char line[1024];
+	char *graft_file;
+	FILE *fp;
+	int i, j;
+
+	while (ref) {
+		if (!strcmp(ref->name, shallow))
+			break;
+		ref = ref->next;
+	}
+	if (!ref)
+		die("No matching ref specified for shallow clone %s",
+		    shallow);
+	if (!server_supports("shallow"))
+		die("The other end does not support shallow clone");
+	packet_write(fd[1], "shallow\n");
+	packet_flush(fd[1]);
+
+	/* Read their graft */
+	prepare_commit_graft();
+	for (;;) {
+		int len;
+		len = packet_read_line(fd[0], line, sizeof(line));
+		if (!len)
+			break;
+		add_graft_info(line);
+	}
+	/* And cauterize at --shallow=<sha1> */
+	sprintf(line, "%s\n", sha1_to_hex(ref->old_sha1));
+	add_graft_info(line);
+
+	/* tell ours */
+	packet_write(fd[1], "custom\n");
+	send_graft_info(fd[1]);
+	packet_flush(fd[1]);
+
+	/* write out ours */
+	graft_file = get_graft_file();
+	fp = fopen(graft_file, "w");
+	if (!fp)
+		die("cannot update grafts!");
+
+	for (i = 0; i < commit_graft_nr; i++) {
+		struct commit_graft *g = commit_graft[i];
+		fputs(sha1_to_hex(g->sha1), fp);
+		for (j = 0; j < g->nr_parent; j++) {
+			fputc(' ', fp);
+			fputs(sha1_to_hex(g->parent[j]), fp);
+		}
+		fputc('\n', fp);
+	}
+	fclose(fp);
+}
 
 static void clone_handshake(int fd[2], struct ref *ref)
 {
 	unsigned char sha1[20];
 
+	if (shallow)
+		shallow_exchange(fd, ref);
+
 	while (ref) {
 		packet_write(fd[1], "want %s\n", sha1_to_hex(ref->old_sha1));
 		ref = ref->next;
@@ -160,6 +221,10 @@ int main(int argc, char **argv)
 				exec = arg + 7;
 				continue;
 			}
+			if (!strncmp("--shallow=", arg, 10)) {
+				shallow = arg + 10;
+				continue;
+			}
 			usage(clone_pack_usage);
 		}
 		dest = arg;
@@ -167,6 +232,8 @@ int main(int argc, char **argv)
 		nr_heads = argc - i - 1;
 		break;
 	}
+	if (shallow && !nr_heads)
+		die("shallow clone needs an explicit head name");
 	if (!dest)
 		usage(clone_pack_usage);
 	pid = git_connect(fd, dest, exec);
diff --git a/commit-tree.c b/commit-tree.c
index 4634b50..cbf2979 100644
--- a/commit-tree.c
+++ b/commit-tree.c
@@ -53,11 +53,6 @@ static void check_valid(unsigned char *s
 	free(buf);
 }
 
-/*
- * Having more than two parents is not strange at all, and this is
- * how multi-way merges are represented.
- */
-#define MAXPARENT (16)
 static unsigned char parent_sha1[MAXPARENT][20];
 
 static const char commit_tree_usage[] = "git-commit-tree <sha1> [-p <sha1>]* < changelog";
diff --git a/commit.c b/commit.c
index 97205bf..a862287 100644
--- a/commit.c
+++ b/commit.c
@@ -102,12 +102,8 @@ static unsigned long parse_commit_date(c
 	return date;
 }
 
-static struct commit_graft {
-	unsigned char sha1[20];
-	int nr_parent;
-	unsigned char parent[0][20]; /* more */
-} **commit_graft;
-static int commit_graft_alloc, commit_graft_nr;
+struct commit_graft **commit_graft;
+int commit_graft_alloc, commit_graft_nr;
 
 static int commit_graft_pos(const unsigned char *sha1)
 {
@@ -128,62 +124,104 @@ static int commit_graft_pos(const unsign
 	return -lo - 1;
 }
 
-static void prepare_commit_graft(void)
+int add_graft_info(char *buf)
 {
-	char *graft_file = get_graft_file();
-	FILE *fp = fopen(graft_file, "r");
+	/* The format is just "Commit Parent1 Parent2 ...\n" */
+	int len = strlen(buf);
+	int i;
+	struct commit_graft *graft = NULL;
+
+	if (buf[len-1] == '\n')
+		buf[--len] = 0;
+	if (buf[0] == '#')
+		return 0;
+	if ((len + 1) % 41) {
+	bad_graft_data:
+		error("bad graft data: %s", buf);
+		free(graft);
+		return -1;
+	}
+	i = (len + 1) / 41 - 1;
+	graft = xmalloc(sizeof(*graft) + 20 * i);
+	graft->nr_parent = i;
+	if (get_sha1_hex(buf, graft->sha1))
+		goto bad_graft_data;
+	for (i = 40; i < len; i += 41) {
+		if (buf[i] != ' ')
+			goto bad_graft_data;
+		if (get_sha1_hex(buf + i + 1, graft->parent[i/41]))
+			goto bad_graft_data;
+	}
+	i = commit_graft_pos(graft->sha1);
+	if (0 <= i) {
+		free(commit_graft[i]);
+		commit_graft[i] = graft;
+		return 0;
+	}
+	i = -i - 1;
+	if (commit_graft_alloc <= ++commit_graft_nr) {
+		commit_graft_alloc = alloc_nr(commit_graft_alloc);
+		commit_graft = xrealloc(commit_graft,
+					sizeof(*commit_graft) *
+					commit_graft_alloc);
+	}
+	if (i < commit_graft_nr)
+		memmove(commit_graft + i + 1,
+			commit_graft + i,
+			(commit_graft_nr - i - 1) *
+			sizeof(*commit_graft));
+	commit_graft[i] = graft;
+	return 0;
+}
+
+void clear_commit_graft(void)
+{
+	int i;
+	for (i = 0; i < commit_graft_nr; i++)
+		free(commit_graft[i]);
+	free(commit_graft);
+	commit_graft_nr = commit_graft_alloc = 0;
+	commit_graft = NULL;
+}
+
+void prepare_commit_graft(void)
+{
+	char *graft_file;
+	FILE *fp;
 	char buf[1024];
+
+	if (getenv(GRAFT_INFO_ENVIRONMENT)) {
+		char *cp, *ep;
+		for (cp = getenv(GRAFT_INFO_ENVIRONMENT);
+		     *cp;
+		     cp = ep) {
+			int more = 0;
+			ep = strchr(cp, '\n');
+			if (ep) {
+				more = 1;
+				*ep = '\0';
+			}
+			else {
+				ep = cp + strlen(cp);
+			}
+			if (ep != cp)
+				add_graft_info(cp);
+			if (!more)
+				break;
+			*ep = '\n';
+			ep++;
+		}
+		return;
+	}
+	graft_file = get_graft_file();
+	fp = fopen(graft_file, "r");
 	if (!fp) {
-		commit_graft = (struct commit_graft **) "hack";
+		commit_graft = (struct commit_graft **) xmalloc(1);
 		return;
 	}
-	while (fgets(buf, sizeof(buf), fp)) {
-		/* The format is just "Commit Parent1 Parent2 ...\n" */
-		int len = strlen(buf);
-		int i;
-		struct commit_graft *graft = NULL;
+	while (fgets(buf, sizeof(buf), fp))
+		add_graft_info(buf);
 
-		if (buf[len-1] == '\n')
-			buf[--len] = 0;
-		if (buf[0] == '#')
-			continue;
-		if ((len + 1) % 41) {
-		bad_graft_data:
-			error("bad graft data: %s", buf);
-			free(graft);
-			continue;
-		}
-		i = (len + 1) / 41 - 1;
-		graft = xmalloc(sizeof(*graft) + 20 * i);
-		graft->nr_parent = i;
-		if (get_sha1_hex(buf, graft->sha1))
-			goto bad_graft_data;
-		for (i = 40; i < len; i += 41) {
-			if (buf[i] != ' ')
-				goto bad_graft_data;
-			if (get_sha1_hex(buf + i + 1, graft->parent[i/41]))
-				goto bad_graft_data;
-		}
-		i = commit_graft_pos(graft->sha1);
-		if (0 <= i) {
-			error("duplicate graft data: %s", buf);
-			free(graft);
-			continue;
-		}
-		i = -i - 1;
-		if (commit_graft_alloc <= ++commit_graft_nr) {
-			commit_graft_alloc = alloc_nr(commit_graft_alloc);
-			commit_graft = xrealloc(commit_graft,
-						sizeof(*commit_graft) *
-						commit_graft_alloc);
-		}
-		if (i < commit_graft_nr)
-			memmove(commit_graft + i + 1,
-				commit_graft + i,
-				(commit_graft_nr - i - 1) *
-				sizeof(*commit_graft));
-		commit_graft[i] = graft;
-	}
 	fclose(fp);
 }
 
@@ -288,6 +326,30 @@ int parse_commit(struct commit *item)
 	return ret;
 }
 
+static void reparse_commit_parents(struct object *o)
+{
+	struct commit *c;
+	struct commit_list *parents;
+	if ((o->type != commit_type) || !o->parsed)
+		return;
+	c = (struct commit *)o;
+	parents = c->parents;
+	o->parsed = 0;
+	while (parents) {
+		struct commit_list *next = parents->next;
+		free(parents);
+		parents = next;
+	}
+	c->parents = NULL;
+	free(c->buffer);
+	c->buffer = NULL;
+}
+
+void reparse_all_parsed_commits(void)
+{
+	for_each_object(reparse_commit_parents);
+}
+
 struct commit_list *commit_list_insert(struct commit *item, struct commit_list **list_p)
 {
 	struct commit_list *new_list = xmalloc(sizeof(struct commit_list));
diff --git a/commit.h b/commit.h
index 986b22d..abc5b9e 100644
--- a/commit.h
+++ b/commit.h
@@ -17,6 +17,20 @@ struct commit {
 	char *buffer;
 };
 
+struct commit_graft {
+	unsigned char sha1[20];
+	int nr_parent;
+	unsigned char parent[0][20]; /* more */
+};
+
+extern struct commit_graft **commit_graft;
+extern int commit_graft_alloc, commit_graft_nr;
+
+extern void prepare_commit_graft(void);
+extern void clear_commit_graft(void);
+extern int add_graft_info(char *);
+extern void reparse_all_parsed_commits(void);
+
 extern int save_commit_buffer;
 extern const char *commit_type;
 
diff --git a/connect.c b/connect.c
index 3f2d65c..046d1da 100644
--- a/connect.c
+++ b/connect.c
@@ -3,6 +3,7 @@
 #include "pkt-line.h"
 #include "quote.h"
 #include "refs.h"
+#include "commit.h"
 #include <sys/wait.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -298,6 +299,29 @@ int match_refs(struct ref *src, struct r
 	return 0;
 }
 
+void send_graft_info(int outfd)
+{
+	int i, j;
+	char packet_buf[41*MAXPARENT], *buf;
+
+	for (i = 0; i < commit_graft_nr; i++) {
+		struct commit_graft *g = commit_graft[i];
+		buf = packet_buf;
+		memcpy(buf, sha1_to_hex(g->sha1), 40);
+		buf += 40;
+		if (MAXPARENT <= g->nr_parent)
+			die("insanely big octopus graft with %d parents: %s",
+			    g->nr_parent, sha1_to_hex(g->sha1));
+		for (j = 0; j < g->nr_parent; j++) {
+			*buf++ = ' ';
+			memcpy(buf, sha1_to_hex(g->parent[j]), 40);
+			buf += 40;
+		}
+		*buf = 0;
+		packet_write(outfd, "%s\n", packet_buf);
+	}
+}
+
 enum protocol {
 	PROTO_LOCAL = 1,
 	PROTO_SSH,
diff --git a/object.c b/object.c
index 1577f74..bbcfcd8 100644
--- a/object.c
+++ b/object.c
@@ -252,3 +252,10 @@ int object_list_contains(struct object_l
 	}
 	return 0;
 }
+
+void for_each_object(void (*fn)(struct object *))
+{
+	int i;
+	for (i = 0; i < nr_objs; i++)
+		fn(objs[i]);
+}
diff --git a/object.h b/object.h
index 0e76182..b4c9729 100644
--- a/object.h
+++ b/object.h
@@ -55,4 +55,6 @@ unsigned object_list_length(struct objec
 
 int object_list_contains(struct object_list *list, struct object *obj);
 
+void for_each_object(void (*)(struct object *));
+
 #endif /* OBJECT_H */
diff --git a/upload-pack.c b/upload-pack.c
index d198055..90ea549 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -13,11 +13,16 @@ static const char upload_pack_usage[] = 
 #define WANTED (1U << 2)
 #define MAX_HAS 256
 #define MAX_NEEDS 256
-static int nr_has = 0, nr_needs = 0, multi_ack = 0, nr_our_refs = 0;
+#define MAX_PARENTS 20
+static int nr_has = 0, nr_needs = 0, nr_our_refs = 0;
 static unsigned char has_sha1[MAX_HAS][20];
 static unsigned char needs_sha1[MAX_NEEDS][20];
 static unsigned int timeout = 0;
 
+/* protocol extensions */
+static int multi_ack = 0;
+static int using_custom_graft = 0;
+
 static void reset_timeout(void)
 {
 	alarm(timeout);
@@ -163,6 +168,77 @@ static int get_common_commits(void)
 	}
 }
 
+static void exchange_grafts(void)
+{
+	int len;
+	char line[41*MAX_PARENTS];
+
+	/* We heard "shallow"; drop up to the next flush */
+	for (;;) {
+		len = packet_read_line(0, line, sizeof(line));
+		reset_timeout();
+		if (!len)
+			break;
+	}
+
+	/* Send our graft */
+	prepare_commit_graft();
+	send_graft_info(1);
+	packet_flush(1);
+
+	/* For precise common commits discovery, we need to use
+	 * the graft information we received from them.
+	 * But this is expensive, so the downloader first says
+	 * if it wants to use our graft as is.
+	 */
+	len = packet_read_line(0, line, sizeof(line));
+	reset_timeout();
+	if (!len)
+		; /* use ours as is */
+	else if (!strcmp(line, "custom\n")) {
+		using_custom_graft = 1;
+		clear_commit_graft();
+		for (;;) {
+			len = packet_read_line(0, line, sizeof(line));
+			reset_timeout();
+			if (!len)
+				break;
+			if (add_graft_info(line))
+				die("Bad graft line %s", line);
+		}
+		/* And using that, we prepare our end. */
+		reparse_all_parsed_commits();
+	}
+	else
+		die("expected 'custom', got '%s'", line);
+}
+
+static void setup_custom_graft(void)
+{
+	char *graft_env = strdup(GRAFT_INFO_ENVIRONMENT "=");
+	int envlen = strlen(graft_env);
+	int i, j;
+
+	for (i = 0; i < commit_graft_nr; i++) {
+		struct commit_graft *g = commit_graft[i];
+		char buf[41*MAX_PARENTS], *ptr;
+		ptr = buf;
+		memcpy(ptr, sha1_to_hex(g->sha1), 40);
+		ptr += 40;
+		for (j = 0; j < g->nr_parent; j++) {
+			*ptr++ = ' ';
+			memcpy(ptr, sha1_to_hex(g->parent[j]), 40);
+			ptr += 40;
+		}
+		*ptr++ = '\n';
+		*ptr = 0;
+		graft_env = xrealloc(graft_env, envlen + (ptr - buf));
+		memcpy(graft_env + envlen, buf, ptr - buf + 1);
+		envlen += ptr - buf;
+	}
+	putenv(graft_env);
+}
+
 static int receive_needs(void)
 {
 	static char line[1000];
@@ -180,16 +256,22 @@ static int receive_needs(void)
 		sha1_buf = dummy;
 		if (needs == MAX_NEEDS) {
 			fprintf(stderr,
-				"warning: supporting only a max of %d requests. "
+				"warning: supporting only a max of "
+				"%d requests. "
 				"sending everything instead.\n",
 				MAX_NEEDS);
 		}
 		else if (needs < MAX_NEEDS)
 			sha1_buf = needs_sha1[needs];
 
-		if (strncmp("want ", line, 5) || get_sha1_hex(line+5, sha1_buf))
+		if (!strcmp("shallow\n", line)) {
+			exchange_grafts();
+			continue;
+		}
+		if (strncmp("want ", line, 5) ||
+		    get_sha1_hex(line+5, sha1_buf))
 			die("git-upload-pack: protocol error, "
-			    "expected to get sha, not '%s'", line);
+			    "expected to get want-sha1, not '%s'", line);
 		if (strstr(line+45, "multi_ack"))
 			multi_ack = 1;
 
@@ -213,7 +295,7 @@ static int receive_needs(void)
 
 static int send_ref(const char *refname, const unsigned char *sha1)
 {
-	static char *capabilities = "multi_ack";
+	static char *capabilities = "multi_ack shallow";
 	struct object *o = parse_object(sha1);
 
 	if (capabilities)
@@ -243,6 +325,8 @@ static int upload_pack(void)
 	if (!nr_needs)
 		return 0;
 	get_common_commits();
+	if (using_custom_graft)
+		setup_custom_graft();
 	create_pack_file();
 	return 0;
 }
-- 
1.1.6.gefef

^ permalink raw reply related

* Re: [Census] So who uses git?
From: Johannes Schindelin @ 2006-01-31 10:27 UTC (permalink / raw)
  To: Carl Baldwin
  Cc: Junio C Hamano, Keith Packard, Martin Langhoff, Linus Torvalds,
	Git Mailing List
In-Reply-To: <20060130185822.GA24487@hpsvcnb.fc.hp.com>

Hi,

On Mon, 30 Jan 2006, Carl Baldwin wrote:

> In general, I think it is grasping the reason for the index file and how 
> git commands like git-commit and git-diff interact with it.

IMHO this is the one big showstopper. I had problems explaining the 
concept myself.

For example, I had a hard time explaining to a friend why a git-add'ed 
file is committed when saying "git commit some_other_file", but not 
another (modified) file. Very unintuitive.

Ciao,
Dscho

^ permalink raw reply

* Re: git-http-fetch failure/segfault -- alas no patch
From: Uwe Zeisberger @ 2006-01-31  9:32 UTC (permalink / raw)
  To: Mark Wooding; +Cc: git
In-Reply-To: <17374.30792.548889.344768@metalzone.distorted.org.uk>

Hello,

Mark Wooding wrote:
> (Yes, that repository exists and is live; the server is fairly
> well-connected.  FWIW, I've put up a tarball of the repository called
> .../funt.git.tar.gz too.)  You ought to be greeted with text like this:
> 
>   error: Unable to find b4f495485ca9ae825ec8c504cdcf24652342f43c under
>   http://boyle.nsict.org/~mdw/funt/.git/
> 
>   Cannot obtain needed commit b4f495485ca9ae825ec8c504cdcf24652342f43c
>   while processing commit 351c72525b9ee5b2321c65598ce82a4e79015012.
> 
> If you're very lucky, git-http-fetch will segfault.
I have the same problem here with an other http repo.  I just finished
bisecting when i got your mail.

The offending commit is 056211053b7516a57ff7a6dd02f503ecef6fca70:

git-clone: do not special case dumb http.

Best regards
Uwe


-- 
Uwe Zeisberger

primes where sieve (p:xs) = [ x | x<-xs, x `rem` p /= 0 ]; \
primes = map head (iterate sieve [2..])

^ permalink raw reply

* Re: [RFC] shallow clone
From: Franck @ 2006-01-31  9:00 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git Mailing List
In-Reply-To: <43DF1F1D.1060704@innova-card.com>

2006/1/31, Franck Bui-Huu <fbh.work@gmail.com>:
> Junio C Hamano wrote:
> > Shallow History Cloning
> > =======================
> >
> > One good thing about git repository is that each clone is a
> > freestanding and complete entity, and you can keep developing in
> > it offline, without talking to the outside world, knowing that
> > you can sync with them later when online.
> >

could we be able to make a public repository from such repo ?

> > It is also a bad thing.  It gives people working on projects
> > with long development history stored in CVS a heart attack when
> > we tell them that their clones need to store the whole history.
> >

yeah and I haven't survive :)
I didn't notice that other people were asking for this feature, that's great !

> > There was a suggestion by Linus to allow a partial clone using a
> > syntax like this:

[snip]

> >
> > There are some issues.
> >
> > . In the fetch above to obtain everything after v2.6.14, and
> >   future runs of `git fetch origin`, if a blob that is in the
> >   commit being fetched happens to match what used to be in a
> >   commit that is older than v2.6.14 (e.g. a patch was reverted),
> >   `upload-pack` running on the other end is free to omit sending
> >   it, because we are telling it that we are up to date with
> >   respect to v2.6.14.  Although I think the current `rev-list
> >   --objects` implementation does not always do such a revert
> >   optimization if the revert is to a blob in a revision that is
> >   sufficiently old, it is free to optimize more aggressively in
> >   the future.
> >

oops, I wasn't aware of that. I still can resolve this issue by hand, no ?

> > . Later when the user decides to fetch older history, the
> >   operation can become a bit cumbersome.
> >

[snip]

> >
> > Design
> > ------
> >
> > First, to bootstrap the process, we would need to add a way to
> > obtain all objects associated with a commit.  We could do a new
> > program, or we could implement this as a protocol extension to
> > `upload-pack`.  My current inclination is the latter.

is the document in "Documentation/technical/pack-protocol.txt"
uptodate ? I can't find anything on multi_ack for example.

> >
> > When talking with `upload-pack` that supports this extension,
> > the downloader can give one commit object name and get a pack
> > that contains all the objects in the tree associated with that
> > commit, plus the commit object itself.  This is a rough
> > equivalent of running the commit walker with the `-t` flag.

[snip]

> >
> >
> > Anybody want to try?
> >

well, you made almost the job with your analysis, but I've never took
a look to git deep internals and with my lack of time, it would take
too much time...

Thanks
--
               Franck

^ permalink raw reply

* Re: [RFC] shallow clone
From: Junio C Hamano @ 2006-01-31  8:51 UTC (permalink / raw)
  To: Franck; +Cc: git
In-Reply-To: <cda58cb80601310037s58989b26s@mail.gmail.com>

Franck <vagabon.xyz@gmail.com> writes:

> I built my public repository from a cautorized one and everybody who
> is pulling from mine is aware of the lack of the full history but they
> actually don't care. If someone is pulling from my repo, he actually
> wants to work on my project which do not need any old thing...

Mind writing up a howto on the topic?

 - How things are set up using the current tool.
 - How others initially clone from you.
 - How others update (pull) from you.
 - What are the pitfalls you and others need to avoid
   (i.e. operations that involve old history)

I brought this up, because lack of official support of shallow
cloning was cited as one of the showstopper for a project that
once considered switching to git but didn't, from a mailing list
research.

^ permalink raw reply

* Re: [RFC] shallow clone
From: Franck @ 2006-01-31  8:37 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Simon Richter, git
In-Reply-To: <7v64o18qn4.fsf@assigned-by-dhcp.cox.net>

2006/1/30, Junio C Hamano <junkio@cox.net>:
> Simon Richter <Simon.Richter@hogyros.de> writes:
>
> >> - disallow fetching from this repo, and
> >
> > Why? It's perfectly acceptable to pull from an incomplete repo, as
> > long as you don't care about the old history.
>
> I agree.  As long as the cloned one can record itself as a
> shallow one (and with what epochs), I do not see a reason to
> forbid second generation clone from a shallow repository.
>

I agree too

> Cauterizing is not any more special than other grafts entries.
> If you have grafted historical kernel repository behind the
> official kernel repository with 2.6.12-rc2 epoch, I do not think
> of any reason to forbid people from cloning such with the
> grafts.
>

I built my public repository from a cautorized one and everybody who
is pulling from mine is aware of the lack of the full history but they
actually don't care. If someone is pulling from my repo, he actually
wants to work on my project which do not need any old thing...

Thanks
--
               Franck

^ permalink raw reply

* [PATCH] Make apply accept the -pNUM option like patch does.
From: Daniel Barkalow @ 2006-01-31  5:36 UTC (permalink / raw)
  To: Ian Molton; +Cc: git
In-Reply-To: <43DE1DB7.20909@f2s.com>

This only applies to traditional diffs, not to git diffs.

Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>

---
On Mon, 30 Jan 2006, Ian Molton wrote:

> Hi.
> 
> is there any reason why git insists diffs be -p1 format ?

Try this patch. Completely untested; if it works, tell Junio. :)

 Documentation/git-apply.txt |    6 +++++-
 apply.c                     |    8 ++++++--
 2 files changed, 11 insertions(+), 3 deletions(-)

2490f3129103a0eae9013eb2a6f564f4a7290fbd
diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt
index 51c7d47..75076b6 100644
--- a/Documentation/git-apply.txt
+++ b/Documentation/git-apply.txt
@@ -10,7 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git-apply' [--stat] [--numstat] [--summary] [--check] [--index] [--apply]
-	  [--no-add] [--index-info] [--allow-binary-replacement] [-z]
+	  [--no-add] [--index-info] [--allow-binary-replacement] [-z] [-pNUM]
 	  [<patch>...]
 
 DESCRIPTION
@@ -68,6 +68,10 @@ OPTIONS
 	backslash characters replaced with `\t`, `\n`, and `\\`,
 	respectively.
 
+-p<n>::
+	Remove <n> leading slashes from traditional diff paths. The
+	default is 1.
+
 --apply::
 	If you use any of the options marked ``Turns off
 	"apply"'' above, git-apply reads and outputs the
diff --git a/apply.c b/apply.c
index c471a82..79e23a7 100644
--- a/apply.c
+++ b/apply.c
@@ -19,6 +19,7 @@
 static const char *prefix;
 static int prefix_length = -1;
 
+static int p_value = 1;
 static int allow_binary_replacement = 0;
 static int check_index = 0;
 static int write_index = 0;
@@ -31,7 +32,7 @@ static int no_add = 0;
 static int show_index_info = 0;
 static int line_termination = '\n';
 static const char apply_usage[] =
-"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [-z] <patch>...";
+"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [-z] [-pNUM] <patch>...";
 
 /*
  * For "diff-stat" like behaviour, we keep track of the biggest change
@@ -217,7 +218,6 @@ static char * find_name(const char *line
  */
 static void parse_traditional_patch(const char *first, const char *second, struct patch *patch)
 {
-	int p_value = 1;
 	char *name;
 
 	first += 4;	// skip "--- "
@@ -1799,6 +1799,10 @@ int main(int argc, char **argv)
 			excludes = x;
 			continue;
 		}
+		if (!strncmp(arg, "-p", 2)) {
+			p_value = atoi(arg + 2);
+			continue;
+		}
 		if (!strcmp(arg, "--no-add")) {
 			no_add = 1;
 			continue;
-- 
0.99.6.g3480

^ permalink raw reply related

* Re: git vs git
From: Hendrik Visage @ 2006-01-31  5:05 UTC (permalink / raw)
  To: Martin Langhoff; +Cc: david, git
In-Reply-To: <46a038f90601301216n793f0eb5k34a2b5a7c4e7491e@mail.gmail.com>

On 1/30/06, Martin Langhoff <martin.langhoff@gmail.com> wrote:
> On 1/31/06, Hendrik Visage <hvjunk@gmail.com> wrote:
> > git isn't
> > working because the wrong git is in the right place :(
>
> Well, I just hit this yesterday on a colleage's machine who was trying
> to get going with git.His first try was to `apt-get install git` and
> as that didn't lead anywhere he fetched the git (scm) sources and
> built them.
>
<snip>

> Not sure how to deal with this. Packages already record (or can
> record) it as a conflict, but source built stuff is different. Perhaps
> during `make install` we should try and exec git --version towards the
> end and print a big fat warning?

Or stop the egos and do a name change as would be the honourable way
especially as gitscm is less than a year old...

--
Hendrik Visage

^ permalink raw reply

* [Cogito] Various bugs
From: Jonas Fonseca @ 2006-01-31  4:13 UTC (permalink / raw)
  To: git; +Cc: Petr Baudis

A few Cogito bugs I found yesterday.

 - cg-fetch between local repos fails when the cloned branch URL does
   not point to a .git directory and a needed object from the repository
   being cloned is packed. git-local-fetch expects a .git directory.

 - cg-commit -c will do the wrong thing (use the invokers gecos info)
   when the author name is empty. One workaround is to make
   pick_author_script append a space at the end of the GIT_* variables.
   GIT will strip those and no gecos info is used.

 - cg-status reports a deleted file both as deleted and as unknown:

	fonseca@antimatter:~/src/elinks/0.12 > git --version
	git version 1.1.6.g1506
	fonseca@antimatter:~/src/elinks/0.12 > cg --version
	cogito-0.17pre.GIT (d3aa9a2b3375e36c774ea477492db76baa1db03e)
	fonseca@antimatter:~/src/elinks/0.12 > cg rm AUTHORS
	Removing file AUTHORS
	fonseca@antimatter:~/src/elinks/0.12 > cg status | grep AUTHORS
	? AUTHORS
	D AUTHORS

-- 
Jonas Fonseca

^ permalink raw reply

* Re: [PATCH] cvs-migration documentation update
From: J. Bruce Fields @ 2006-01-31  3:40 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7virs13x1i.fsf@assigned-by-dhcp.cox.net>

On Mon, Jan 30, 2006 at 07:18:17PM -0800, Junio C Hamano wrote:
> "J. Bruce Fields" <bfields@fieldses.org> writes:
> 
> > Here's some changes to the cvs-migration.txt.  As usual, in my attempt
> > to make things clearer someone may have found I've made them less so, or
> > I may have just gotten something wrong; so any review is welcomed.
> 
> Again, thanks for doing this.

Hey, it's fun.

> > -..., and the
> > -first step to recovery is admitting you have a problem. The fact that
> > -you are reading this file means that you may be well on that path
> > -already.
> > -
> > -The thing about CVS is that it absolutely sucks...
> > -
> > -One particular suckage of CVS is very hard to work around: CVS is...
> 
> Somehow I miss the above two paragraphs and a half ;-).

Hah.  Yes, understood.  But I figured a reader trying to migrate away
from CVS is more painfully aware of the above than anyone, so better to
just get out of their way and let them get on with it....

> But listing the differences as bullet points as you did makes
> things much clearer.  I like it.

OK!  Good.

> > +If some else has updated the repository more recently, `git push`, like
> 
> some else?

Whoops, thanks for noticing, should be "someone", obviously.

Let me know if you'd like a revised patch.--b.

^ permalink raw reply

* Re: [PATCH] cvs-migration documentation update
From: Junio C Hamano @ 2006-01-31  3:18 UTC (permalink / raw)
  To: J. Bruce Fields; +Cc: git
In-Reply-To: <20060129043147.GA9581@fieldses.org>

"J. Bruce Fields" <bfields@fieldses.org> writes:

> Here's some changes to the cvs-migration.txt.  As usual, in my attempt
> to make things clearer someone may have found I've made them less so, or
> I may have just gotten something wrong; so any review is welcomed.

Again, thanks for doing this.

> I moved the material describing shared repository management from
> core-tutorial.txt to cvs-migration.txt, where it seems more appropriate,
> and combined two sections to eliminate some redundancy.

Seems sensible.

> diff --git a/Documentation/cvs-migration.txt...
> index 8fd1a33..2bd58d3 100644
> --- a/Documentation/cvs-migration.txt
> +++ b/Documentation/cvs-migration.txt
> @@ -1,126 +1,182 @@
>  git for CVS users
>  =================
>  
> -..., and the
> -first step to recovery is admitting you have a problem. The fact that
> -you are reading this file means that you may be well on that path
> -already.
> -
> -The thing about CVS is that it absolutely sucks...
> -
> -One particular suckage of CVS is very hard to work around: CVS is...

Somehow I miss the above two paragraphs and a half ;-).
But listing the differences as bullet points as you did makes
things much clearer.  I like it.

> +------------------------------------------------
> +$ git push origin master
> +------------------------------------------------
> +
> +If some else has updated the repository more recently, `git push`, like

some else?

^ permalink raw reply

* git-http-fetch failure/segfault -- alas no patch
From: Mark Wooding @ 2006-01-30 20:34 UTC (permalink / raw)
  To: git

[This is a repost -- sorry!  I fouled up the last one by missing the
subject off, which makes me look like a prize pillock.  I also failed to
mention the relevant versions, so let me try again.  I do actually have
a brain, honest; it's just not working at the moment for some reason.]

git-http-fetch seems buggy.  (This is in both 1.1.5 and 1506fc34... on
the git.kernel.org master -- same symptoms.)

I /think/ it's getting confused by a combination of a large top-level
tree (lots of blobs directly attached) attached to the top commit,
together with most of the things being packed.

To illustrate the bug, create a repository with the following shell
script.  (It will create a working tree called `funt' with a little GIT
history inside.)

----
#! /bin/sh

set -e
mkdir funt
cd funt
git-init-db 
yes | nl | head -200 | while read n hunoz; do echo file $n >foo.$n; done
git-add *
echo Boo. | git-commit -F - -a
git-repack
git-prune-packed 
echo Censored >foo.197
echo Ouch. | git-commit -F - -a
git-update-server-info
----

Then put the repository somewhere your web server will let you get to
it, and try to clone it, say using

  git-clone http://boyle.nsict.org/~mdw/funt.git

(Yes, that repository exists and is live; the server is fairly
well-connected.  FWIW, I've put up a tarball of the repository called
.../funt.git.tar.gz too.)  You ought to be greeted with text like this:

  error: Unable to find b4f495485ca9ae825ec8c504cdcf24652342f43c under
  http://boyle.nsict.org/~mdw/funt/.git/

  Cannot obtain needed commit b4f495485ca9ae825ec8c504cdcf24652342f43c
  while processing commit 351c72525b9ee5b2321c65598ce82a4e79015012.

If you're very lucky, git-http-fetch will segfault.

What's going on here?

Think about the repository layout for a bit.  There's a `big' pack file,
and a little commit.  The commit has an unpacked tree attached, but
almost all of its leaves are in the pack.  The commit's parent is
packed.

So git-http-fetch starts by filling its queue with prefetches for blob
objects which are packed (and so it gets 404s for them).  This is fine.
However! when it comes to collect the parent commit, it realises it
needs to fetch the pack list.  Unfortunately, something goes wrong in
run_active_slot.  As far as I can make out, the slot used to collect
.../info/packs is being /reused/ by fill_active_slots (called by
step_active_slots) before fetch_indices is returned to.  Since the
prefetch which got the new slot is for an object which got packed, it
fails with a 404, which is written back to the slot.  The result is that
fetch_indices thinks that the pack list doesn't exist (even though it
actually does, and libcurl fetched it just fine, thanks).  This is
marked as a permanent error, and that parent commit can't be found.

The segfault is I think due to this reuse too, but it only happens
sometimes and I'm not entirely clear on why.

I'm afraid I don't have a patch.  I've spent a little while trying to
fix this bug myself, but my changes just seem to cause wedging, or fd
leaks, or segfaults, or all three, so it's obvious I don't understand
the code well enough.

-- [mdw]

^ permalink raw reply

* Re: [PATCH] Set errno to EEXIST if mkdir returns EACCES or EPERM
From: Junio C Hamano @ 2006-01-30 20:33 UTC (permalink / raw)
  To: Alex Riesen; +Cc: git
In-Reply-To: <20060130193839.GA6575@steel.home>

Alex Riesen <raa.lkml@gmail.com> writes:

> ... and the directory already exists. I.E. Cygwin is such
> a case: mkdir fail for mounts which reference directly
> to windows mounts ("drives").
>
> ---
>
> The discussion, which ended up with this patch can be read
> here: http://www.cygwin.com/ml/cygwin/2006-01/msg01276.html
>
> BTW, there is this:
> http://www.cygwin.com/ml/cygwin/2006-01/msg01380.html
> So this patch will probably be not needed soon.

Thanks for all the background information.  Although it is very
tempting for me to adopt your patch as an easy way out, I would
feel *dirty* if I did so.

Eric Blake is right in his argument in that thread.  Our code
should not depend on the Linux EEXIST behaviour.  The reason
Cygwin folks want to be as close to Linux is to work around
application bugs like this.  Which is a valid concern for them,
but it does not mean the application has license to depend on
Linux behaviour.

We, as an application, should take a different attitude -- we
should fix things to make things portable, not work things
around, if both are equally easily doable.  I do not object to
using a function that has a semantics Linux mkdir() gives us,
but calling that mkdir() does not feel quite right.  

Also the wrapper implies that in our future use of mkdir() we
cannot tell the difference between EEXIST and other errors if we
later wanted to.

So let's look at our existing uses first:

apply.c:1577:		if (mkdir(buf, 0777) < 0) {
apply.c-1578-			if (errno != EEXIST)
apply.c-1579-				break;
apply.c-1580-		}
apply.c-1581-	}

This is "we want to see buf directory exist and we would create
one if there isn't".  Instead of checking errno, we could stat
as your patch does.

entry.c:15:		if (mkdir(buf, 0777)) {
entry.c-16-			if (errno == EEXIST) {
entry.c-17-				struct stat st;
entry.c:18:				if (len > state->base_dir_len && state->force && !unlink(buf) && !mkdir(buf, 0777))
entry.c-19-					continue;
entry.c-20-				if (!stat(buf, &st) && S_ISDIR(st.st_mode))
entry.c-21-					continue; /* ok */
entry.c-22-			}

This is a bit more involved. "we want to have buf directory and
we would create it, and if force is given to have something
under that directory, we would even unlink the nondirectory that
sits there".

I asked "git-grep" where else we use mkdir(), and all other
users want the semantics of the apply.c use quoted above.

So I'd rather see us create a generic helper function like this:

	int make_directory(const char *path, int force)
        {
		struct stat st;
		int mkdir_errno;
		if (!mkdir(path, 0777))
			return 0;
                mkdir_errno = errno;
		if (!lstat(path, &st) && S_ISDIR(st.st_mode))
                	return 0;
                if (!force) {
		bad:
                	errno = mkdir_errno;
                        return -1;
                }
                if (!unlink(path, &st) && !mkdir(path, 0777))
                	return 0;
                /* we might have failed to unlink an existing symlink
		 * which happens to point at an existing directory; that
                 * directory is not what we want here.
                 */
		if (!lstat(path, &st) && S_ISDIR(st.st_mode))
                	return 0;
		goto bad;
        }

and have current callers of mkdir() use it, regardless of the
platform.  It may not worth saving mkdir_errno, though.

Then everybody but entry.c one would say force=0, and entry.c
one passes force appropriately using the condition it uses in
its current if() statement.

^ permalink raw reply

* Re: git vs git
From: Martin Langhoff @ 2006-01-30 20:16 UTC (permalink / raw)
  To: Hendrik Visage; +Cc: david, git
In-Reply-To: <d93f04c70601300714i4b7b3b58qa5aa151e3e42a413@mail.gmail.com>

On 1/31/06, Hendrik Visage <hvjunk@gmail.com> wrote:
> git isn't
> working because the wrong git is in the right place :(

Well, I just hit this yesterday on a colleage's machine who was trying
to get going with git.His first try was to `apt-get install git` and
as that didn't lead anywhere he fetched the git (scm) sources and
built them.

Apparently GNU GIT's git binary was earlier in the path than GIT SCM's
and so stuff broke very creatively. As soon as I did `git --version` I
understood what was happening and a swift `apt-get remove git` fixed
it. But it can sure mess the day for any user trying to install git
naively.

Not sure how to deal with this. Packages already record (or can
record) it as a conflict, but source built stuff is different. Perhaps
during `make install` we should try and exec git --version towards the
end and print a big fat warning?

cheers,


m

^ permalink raw reply

* Re: Importing diffs
From: Greg KH @ 2006-01-30 19:57 UTC (permalink / raw)
  To: Ian Molton; +Cc: git
In-Reply-To: <43DE1DB7.20909@f2s.com>

On Mon, Jan 30, 2006 at 02:07:51PM +0000, Ian Molton wrote:
> Hi.
> 
> is there any reason why git insists diffs be -p1 format ?

Because that's the default for what the Linux kernel project uses?  :)

> it makes it hard to import a diff generated by svn (-p0).

I'm pretty sure that svn can output -p1 patches, I've done it in the
past...

thanks,

greg k-h

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox