* [PATCH v2 0/3] transport: catch non-fast-forwards
From: Tay Ray Chuan @ 2009-12-08 14:34 UTC (permalink / raw)
To: git
Cc: Shawn O. Pearce, Daniel Barkalow, Sverre Rabbelier,
Clemens Buchacher, Jeff King, Junio C Hamano
In-Reply-To: <20091204125042.c64f347d.rctay89@gmail.com>
Daniel, I've reworked the refactoring of ref status logic, like you
mentioned, such that transport_push() calls the generic function before
calling the transport->push_refs() implementation.
Junio, although this series affects http transports (smart), please treat
this series as separate from 'tr/http-updates' in 'next'.
Summary for those who missed v1:
This patch series applies on top of 'next', and deals with alerting
the user to non-fast-forward pushes when using helpers (smart).
Previously, git silently exited. This situation involves the curl
helper and the smart protocol. The fast-forward push is only detected
when curl executes the rpc client (git-send-pack). Now, we detect it
before telling the helper to push.
Changes from v1:
- reworked refactoring of ref status logic (patch 1)
- rewrote the patch for transport_push() (patch 2)
- minor rewording of commit message (patch 3)
Tay Ray Chuan (3):
refactor ref status logic for pushing
transport.c::transport_push(): make ref status affect return value
transport-helper.c::push_refs(): emit "no refs" error message
builtin-send-pack.c | 50 +++++++++++---------------------------------------
remote.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
remote.h | 2 ++
transport-helper.c | 18 ++++++++++--------
transport.c | 11 +++++++++--
5 files changed, 82 insertions(+), 49 deletions(-)
--
Cheers,
Ray Chuan
^ permalink raw reply
* Re: [BUG] Bad msysgit/egit interaction over dotfiles
From: Erik Faye-Lund @ 2009-12-08 14:23 UTC (permalink / raw)
To: Ferry Huberts; +Cc: Yann Dirson, GIT ml
In-Reply-To: <4B1E57BF.1000500@pelagic.nl>
On Tue, Dec 8, 2009 at 2:42 PM, Ferry Huberts <ferry.huberts@pelagic.nl> wrote:
> On 12/08/2009 02:34 PM, Erik Faye-Lund wrote:
>> On Tue, Dec 8, 2009 at 2:28 PM, Yann Dirson <ydirson@linagora.com> wrote:
>>> I'm not sure who's at fault here - namely, I can't see any valid
>>> reason for eclipse to refuse such writes, but I am not sure it is a
>>> good reason for msysgit would set the hidden bit either. In either
>>> case, even if only for the short term, I think msysgit should ensure
>>> that this bit does not get set (possibly circumventing any magic msys
>>> would do behind its back).
>>
>> Setting the config option "core.hidedotfiles" to "false" should
>> prevent this from happening.
>>
>
> why isn't this the default?
>
> I also experienced this change in behaviour and I thought we would
> strive to keep the experience the same.
>
You can follow the discussion here:
http://code.google.com/p/msysgit/issues/detail?id=288
I believe the reason is something like "because someone suggested it,
and no one disagreed". Do you have a good argument why it shouldn't be
the default (other than "it's a change", because changing it back now
would also be a change)?
--
Erik "kusma" Faye-Lund
^ permalink raw reply
* Re: [PATCH] Add commit.status, --status, and --no-status
From: James P. Howard, II @ 2009-12-08 14:07 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Jeff King, git
In-Reply-To: <7vr5r6ndkz.fsf@alter.siamese.dyndns.org>
On Tue, Dec 8, 2009 at 02:13, Junio C Hamano <gitster@pobox.com> wrote:
> Jeff King <peff@peff.net> writes:
>
>> On Mon, Dec 07, 2009 at 05:45:27PM -0500, James P. Howard, II wrote:
>>
>>> This commit provides support for commit.status, --status, and
>>> --no-status, which control whether or not the git status information
>>> is included in the commit message template when using an editor to
>>> prepare the commit message. It does not affect the effects of a
>>> user's commit.template settings.
>>
>> Thanks, this looks very cleanly done. The only complaint I would make is
>> that it should probably include a simple test case.
>
> Yes. Also I am a _bit_ worried about the name "status", as the longer
> term direction is to make "status" not "a preview of commit", may confuse
> people who do read Release Notes.
Right now, this option does not affect how the commit message is prepared
in git tag. If the option were extended to cover that case as well, what would
a sensible name for the option be, then?
James
--
James P. Howard, II, MPA MBCS
jh@jameshoward.us
^ permalink raw reply
* Re: [msysGit] [PATCH/RFC 03/11] mingw: implement syslog
From: Erik Faye-Lund @ 2009-12-08 14:01 UTC (permalink / raw)
To: Johannes Sixt; +Cc: msysgit, git, dotzenlabs
In-Reply-To: <200911272023.58262.j6t@kdbg.org>
On Fri, Nov 27, 2009 at 8:23 PM, Johannes Sixt <j6t@kdbg.org> wrote:
> On Freitag, 27. November 2009, Erik Faye-Lund wrote:
>> On Thu, Nov 26, 2009 at 10:23 PM, Johannes Sixt <j6t@kdbg.org> wrote:
>> > I would
>> >
>> > const char* arg;
>> > if (strcmp(fmt, "%s"))
>> > die("format string of syslog() not implemented")
>> > va_start(va, fmt);
>> > arg = va_arg(va, char*);
>> > va_end(va);
>> >
>> > because we have exactly one invocation of syslog(), which passes "%s" as
>> > format string. Then strbuf_vaddf is not needed. Or even simpler: declare
>> > the function as
>> >
>> > void syslog(int priority, const char *fmt, const char*arg);
>>
>> After reading this again, I agree that this is the best solution. I'll
>> update for the next iteration.
>
> Except that you shouldn't die like I proposed because here we are already in
> the die_routine, no?
>
Might be. Either way, I think loosing a log-entry is better than
taking down the server. I'm just doing a warning() and return. If
we're lucky, the warning gets somewhere. If not, well, something
happened and no one was around to see it.
>> > "Note that the string that you log cannot contain %n, where n is an
>> > integer value (for example, %1) because the event viewer treats it as an
>> > insertion string. ..."
>> >
>> > How are the chances that this condition applies to our use of the
>> > function?
>>
>> Ugh, increasingly high since we're adding IPv6 support, I guess.
>> Perhaps some form of escaping needs to be done?
>
> I think so, but actually I have no clue.
>
Bah, according to Microsoft Support (1), there's no simple way to
escape this. I'm tempted to leave this bug in, and rather try to fix
the symptoms when/if they start popping up. Unless someone else comes
up with something better, that is.
(1) http://support.microsoft.com/kb/934640
--
Erik "kusma" Faye-Lund
^ permalink raw reply
* Re: [BUG] Bad msysgit/egit interaction over dotfiles
From: Ferry Huberts @ 2009-12-08 13:42 UTC (permalink / raw)
To: kusmabite; +Cc: Yann Dirson, GIT ml
In-Reply-To: <40aa078e0912080534x32fe9724xcda47ad46dbdb7c0@mail.gmail.com>
On 12/08/2009 02:34 PM, Erik Faye-Lund wrote:
> On Tue, Dec 8, 2009 at 2:28 PM, Yann Dirson <ydirson@linagora.com> wrote:
>> I'm not sure who's at fault here - namely, I can't see any valid
>> reason for eclipse to refuse such writes, but I am not sure it is a
>> good reason for msysgit would set the hidden bit either. In either
>> case, even if only for the short term, I think msysgit should ensure
>> that this bit does not get set (possibly circumventing any magic msys
>> would do behind its back).
>
> Setting the config option "core.hidedotfiles" to "false" should
> prevent this from happening.
>
why isn't this the default?
I also experienced this change in behaviour and I thought we would
strive to keep the experience the same.
^ permalink raw reply
* Re: [PATCH 0/3] Add a "fix" command to "rebase --interactive"
From: Sverre Rabbelier @ 2009-12-08 13:51 UTC (permalink / raw)
To: Jeff King
Cc: Junio C Hamano, Nanako Shiraishi, Johannes Schindelin,
Matthieu Moy, Michael J Gruber, Michael Haggerty, git
In-Reply-To: <20091208093515.GA32655@sigill.intra.peff.net>
Heya,
On Tue, Dec 8, 2009 at 10:35, Jeff King <peff@peff.net> wrote:
> $ bash
> $ echo "!fixup commit"
> bash: !fixup: event not found
> $ echo "fixup! commit"
> fixup! commit
Speaking of which, must we use that annoying bang? I hate how bash
gets in my way when I try to write a commit message with a a bang in
it, I'd much rather use a different character that is not in risk of
being mistreated by my shell. (Although it seems that bash does do TRT
in the 'fixup!' case.)
--
Cheers,
Sverre Rabbelier
^ permalink raw reply
* Re: [PATCH/RFC 07/11] run-command: support input-fd
From: Erik Faye-Lund @ 2009-12-08 13:46 UTC (permalink / raw)
To: Johannes Sixt; +Cc: msysgit, git, dotzenlabs
In-Reply-To: <200911272114.13107.j6t@kdbg.org>
On Fri, Nov 27, 2009 at 9:14 PM, Johannes Sixt <j6t@kdbg.org> wrote:
> On Freitag, 27. November 2009, Erik Faye-Lund wrote:
>> What do you find confusing about it? The idea is to use a provided
>> bi-directional fd instead of a pipe if async->out is non-zero. The
>> currently defined rules for async is that async->out must be zero
>> (since the structure should be zero-initialized).
>
> It is just the code structure that is confusing. It should be
>
> if (async->out) {
> /* fd was provided */
> do all that is needed in this case
> } else {
> /* fd was requested */
> do all for this other case
> }
> /* nothing to do anymore here */
>
> (Of course, this should only replace the part that is cited above, not the
> whole function.)
>
OK. I've reimplemented the change for the next round, taking this into account.
>> Indeed it does. Do we want to extend it to support a set of
>> unidirectional channels instead?
>
> Yes, I think so. We could pass a regular int fd[2] array around with the clear
> definition that both can be closed independently, i.e. one must be a dup() of
> the other. struct async would also have such an array.
>
OK. This has been included for the next round. Instead of an array,
I've tried to be consistent with start_command, and used two
variables, "in" and "out".
> Speaking of dup(): The underlying function is DuplicateHandle(), and its
> documentation says:
>
> "You should not use DuplicateHandle to duplicate handles to the following
> objects: ... o Sockets. ... use WSADuplicateSocket."
>
> But then the docs of WSADuplicateSocket() talk only about duplicating a socket
> to a separate process. Perhaps DuplicateHandle() of a socket within the same
> process Just Works?
>
It seems the rest of the Windows-world depends on DuplicateHandle()
working for sockets, so I'm not too worried. I can't find anything
documentation(1) for _dup, and I don't think we have our own
dup()-implementation.
(1) http://msdn.microsoft.com/en-us/library/8syseb29(VS.71).aspx
--
Erik "kusma" Faye-Lund
^ permalink raw reply
* Re: help: bisect single file from repos
From: walter harms @ 2009-12-08 13:41 UTC (permalink / raw)
To: Christian Couder; +Cc: Michael J Gruber, git
In-Reply-To: <200912080917.17220.chriscool@tuxfamily.org>
Christian Couder schrieb:
> Hi,
>
> On lundi 07 décembre 2009, walter harms wrote:
>> Michael J Gruber schrieb:
>>> walter harms venit, vidit, dixit 07.12.2009 13:59:
>>>> Hi list,
>>>> i am new to git (using: git version 1.6.0.2).
>>> though your git is not that new ;)
>>>
>>>> I would like to bisect a single file but i have only commit id, no
>>>> tags.
>>>>
>>>> Background:
>>>> I have a copy of the busybox git repos, and i know there is (perhaps)
>>>> a bug in ash.c.
>>>>
>>>> how can i do that ?
>>> You don't need any tags for bisecting. The man page of git-bisect has
>>> several examples on how to use it. Do you have a test script which
>>> exposes the bug?
>> unfortunately no, the error shows up very nicely when booting my
>> embdedded system but not else (this is the reason i would to bisect that
>> file only and not busybox completely). And from the man pages i got the
>> impression that it is only possible the start with a tag.
>
> The man page says:
>
> git bisect start [<bad> [<good>...]] [--] [<paths>...]
>
> and then:
>
> "This command uses git rev-list --bisect to help drive the binary search
> process to find which change introduced a bug, given an old "good" commit
> object name and a later "bad" commit object name."
i am sorry, i am not familiar with git and when i am stating i am looking
for examples first. the examples in my man page are like
git bisect start v2.6.20-rc6 v2.6.20-rc4
there is nothing like:
git bisect start 6a87a68a6a8 65a76a8a68a7
I ASSUME that you can use tags like "v2.6.20-rc6" and commit-id like "6a87a68a6a8"
interchangeable but that was not clear from beginning.
BTW did you notice the sentence says "commit object name" not "commit id" ? when
you are starting you are not familiar with the wording so you do not make the connection.
>> i already had the hint that i need to do:
>> git bisect start bad_commit_id good_commit_id -- ash.c
>
> So did you try that?
>
not yet, we are still using an older version of BB for production. So there is no hurry.
The problem is that we can not found the reason for the bug. NTL i plan for this week.
>> Ntl, there is one more question, how can i make sure that
>> i use the right version ?
>
> If you mean the right git version, then I think any 1.6.X should be enough.
>
>> first i toughed that cherry-pick is the right
>> idea but it seems that that will apply onyl certain patches ?
>
> If you want to find the commit that introduced a bug, then you should not
> need cherry-pick.
>
mmh, no, the idea was to use something like
git "checkou" <id> and having a version that represents THAT moment.
re,
wh
> Regards,
> Christian.
>
^ permalink raw reply
* Re: [msysGit] [PATCH/RFC 08/11] daemon: use explicit file descriptor
From: Erik Faye-Lund @ 2009-12-08 13:38 UTC (permalink / raw)
To: Johannes Sixt; +Cc: msysgit, git, dotzenlabs
In-Reply-To: <200911272128.48974.j6t@kdbg.org>
On Fri, Nov 27, 2009 at 9:28 PM, Johannes Sixt <j6t@kdbg.org> wrote:
> On Freitag, 27. November 2009, Johannes Sixt wrote:
>> On Freitag, 27. November 2009, Erik Faye-Lund wrote:
>> > When I think more about it, I might've broken the inetd-mode as it
>> > should communicate over stdin and stdout (not just stdin as it would
>> > try to do now)... I don't know the inetd internals, but this frightens
>> > me a bit.
>>
>> Do we need inetd mode on Windows? At one time a looked for a inetd-like
>> service, but couldn't find one.
>
> How foolish of me. This affects all platforms. Of course it is an important to
> keep inetd mode.
>
> -- Hannes
>
I believe I've fixed this for the next round, but I haven't been able
to test the inetd-stuff, since I don't have a working
test-environment.
--
Erik "kusma" Faye-Lund
^ permalink raw reply
* Re: [PATCH/RFC 09/11] daemon: use run-command api for async serving
From: Erik Faye-Lund @ 2009-12-08 13:36 UTC (permalink / raw)
To: Johannes Sixt; +Cc: msysgit, git, dotzenlabs
In-Reply-To: <200912022012.08905.j6t@kdbg.org>
On Wed, Dec 2, 2009 at 8:12 PM, Johannes Sixt <j6t@kdbg.org> wrote:
> On Mittwoch, 2. Dezember 2009, Erik Faye-Lund wrote:
>> I'm not entirely sure how to make the interface, though. Any good
>> suggestions?
>
> I suggest to model finish_async_nowait() after waitpid() so that
>
> while ((pid = waitpid(-1, &status, WNOHANG)) > 0) ...
> becomes
> while ((pid = finish_async_nowait(&some_async, &status)) > 0) ...
>
> but where the resulting status is already "decoded", i.e. zero is success and
> non-zero is failure (including death through signal); WIFEXITED and
> WEXITSTATUS should not be applicable to status anymore.
>
> -- Hannes
>
Thanks. Implemented as suggested for the next round.
--
Erik "kusma" Faye-Lund
^ permalink raw reply
* Re: [BUG] Bad msysgit/egit interaction over dotfiles
From: Erik Faye-Lund @ 2009-12-08 13:34 UTC (permalink / raw)
To: Yann Dirson; +Cc: GIT ml
In-Reply-To: <20091208132857.GB5425@linagora.com>
On Tue, Dec 8, 2009 at 2:28 PM, Yann Dirson <ydirson@linagora.com> wrote:
> I'm not sure who's at fault here - namely, I can't see any valid
> reason for eclipse to refuse such writes, but I am not sure it is a
> good reason for msysgit would set the hidden bit either. In either
> case, even if only for the short term, I think msysgit should ensure
> that this bit does not get set (possibly circumventing any magic msys
> would do behind its back).
Setting the config option "core.hidedotfiles" to "false" should
prevent this from happening.
--
Erik "kusma" Faye-Lund
^ permalink raw reply
* [BUG] Bad msysgit/egit interaction over dotfiles
From: Yann Dirson @ 2009-12-08 13:28 UTC (permalink / raw)
To: GIT ml
Some devs here started to use egit on windows, and since egit is not
complete yet, occasionally^Wregularly use msysgit for
rebase/stash/you-name-it.
This revealed a strange problem that took some time figuring out,
where eclipse refused to write to .classpath or .project, just saying
"could not write", while other apps had no problem editing the same
files.
In the end, the problem is that the dotfiles had the "hidden" bit set,
and that for some reason eclipse does not allow to write to hidden
files - and that the one (re)setting the "hidden" bit over and over
again is msysgit, whenever it checkouts such a dotfile - surely to
emulate the unix behaviour of hiding dotfiles by default.
I'm not sure who's at fault here - namely, I can't see any valid
reason for eclipse to refuse such writes, but I am not sure it is a
good reason for msysgit would set the hidden bit either. In either
case, even if only for the short term, I think msysgit should ensure
that this bit does not get set (possibly circumventing any magic msys
would do behind its back).
Best regards,
--
Yann
^ permalink raw reply
* [REROLL PATCH 8/8] Remove special casing of http, https and ftp
From: Ilari Liusvaara @ 2009-12-08 13:16 UTC (permalink / raw)
To: git
In-Reply-To: <1260278177-9029-1-git-send-email-ilari.liusvaara@elisanet.fi>
HTTP, HTTPS and FTP are no longer special to transport code. Also
add support for FTPS (curl supports it so it is easy).
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
.gitignore | 4 ++++
Makefile | 24 ++++++++++++++++++++++--
transport.c | 8 --------
3 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/.gitignore b/.gitignore
index ac02a58..aa7a8ac 100644
--- a/.gitignore
+++ b/.gitignore
@@ -107,6 +107,10 @@
/git-relink
/git-remote
/git-remote-curl
+/git-remote-http
+/git-remote-https
+/git-remote-ftp
+/git-remote-ftps
/git-repack
/git-replace
/git-repo-config
diff --git a/Makefile b/Makefile
index 2ad7e36..546a408 100644
--- a/Makefile
+++ b/Makefile
@@ -424,6 +424,13 @@ BUILT_INS += git-stage$X
BUILT_INS += git-status$X
BUILT_INS += git-whatchanged$X
+#ifdef NO_CURL
+REMOTE_CURL_NAMES =
+#else
+# Yes, this is missing git-remote-http intentionally!
+REMOTE_CURL_NAMES = git-remote-https git-remote-ftp git-remote-ftps
+#endif
+
# what 'all' will build and 'install' will install in gitexecdir,
# excluding programs for built-in commands
ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
@@ -1097,7 +1104,7 @@ else
else
CURL_LIBCURL = -lcurl
endif
- PROGRAMS += git-remote-curl$X git-http-fetch$X
+ PROGRAMS += git-remote-http$X git-remote-https$X git-remote-ftp$X git-remote-ftps$X git-http-fetch$X
curl_check := $(shell (echo 070908; curl-config --vernum) | sort -r | sed -ne 2p)
ifeq "$(curl_check)" "070908"
ifndef NO_EXPAT
@@ -1676,7 +1683,13 @@ git-http-push$X: revision.o http.o http-push.o $(GITLIBS)
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
-git-remote-curl$X: remote-curl.o http.o http-walker.o $(GITLIBS)
+$(REMOTE_CURL_NAMES): git-remote-http$X
+ $(QUIET_LNCP)$(RM) $@ && \
+ ln $< $@ 2>/dev/null || \
+ ln -s $< $@ 2>/dev/null || \
+ cp $< $@
+
+git-remote-http$X: remote-curl.o http.o http-walker.o $(GITLIBS)
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
@@ -1852,6 +1865,7 @@ endif
ifneq (,$X)
$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), test '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p' -ef '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p$X' || $(RM) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p';)
endif
+
bindir=$$(cd '$(DESTDIR_SQ)$(bindir_SQ)' && pwd) && \
execdir=$$(cd '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' && pwd) && \
{ test "$$bindir/" = "$$execdir/" || \
@@ -1865,6 +1879,12 @@ endif
ln -s "git$X" "$$execdir/$$p" 2>/dev/null || \
cp "$$execdir/git$X" "$$execdir/$$p" || exit; \
done; } && \
+ { for p in $(REMOTE_CURL_NAMES); do \
+ $(RM) "$$execdir/$$p" && \
+ ln "$$execdir/git-remote-http$X" "$$execdir/$$p" 2>/dev/null || \
+ ln -s "git-remote-http$X" "$$execdir/$$p" 2>/dev/null || \
+ cp "$$execdir/git-remote-http$X" "$$execdir/$$p" || exit; \
+ done; } && \
./check_bindir "z$$bindir" "z$$execdir" "$$bindir/git-add$X"
install-doc:
diff --git a/transport.c b/transport.c
index 64938fd..211114e 100644
--- a/transport.c
+++ b/transport.c
@@ -932,14 +932,6 @@ struct transport *transport_get(struct remote *remote, const char *url)
data->conn = NULL;
data->got_remote_heads = 0;
- } else if (!prefixcmp(url, "http://")
- || !prefixcmp(url, "https://")
- || !prefixcmp(url, "ftp://")) {
- /* These three are just plain special. */
- transport_helper_init(ret, "curl");
-#ifdef NO_CURL
- error("git was compiled without libcurl support.");
-#endif
} else {
/* Unknown protocol in URL. Pass to external handler. */
int len = external_specification_len(url);
--
1.6.6.rc1.300.gfbc27
^ permalink raw reply related
* [REROLL PATCH 5/8] Support taking over transports
From: Ilari Liusvaara @ 2009-12-08 13:16 UTC (permalink / raw)
To: git
In-Reply-To: <1260278177-9029-1-git-send-email-ilari.liusvaara@elisanet.fi>
Add support for taking over transports that turn out to be smart.
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
transport-helper.c | 16 +++++++++++++++-
transport.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++-----
transport.h | 2 ++
3 files changed, 63 insertions(+), 6 deletions(-)
diff --git a/transport-helper.c b/transport-helper.c
index 0e82553..3b7340c 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -22,6 +22,7 @@ struct helper_data
/* These go from remote name (as in "list") to private name */
struct refspec *refspecs;
int refspec_nr;
+ struct git_transport_options gitoptions;
};
static void sendline(struct helper_data *helper, struct strbuf *buffer)
@@ -91,6 +92,7 @@ static struct child_process *get_helper(struct transport *transport)
const char **refspecs = NULL;
int refspec_nr = 0;
int refspec_alloc = 0;
+ int duped;
if (data->helper)
return data->helper;
@@ -109,9 +111,19 @@ static struct child_process *get_helper(struct transport *transport)
die("Unable to run helper: git %s", helper->argv[0]);
data->helper = helper;
+ /*
+ * Open the output as FILE* so strbuf_getline() can be used.
+ * Do this with duped fd because fclose() will close the fd,
+ * and stuff like taking over will require the fd to remain.
+ *
+ */
+ duped = dup(helper->out);
+ if (duped < 0)
+ die_errno("Can't dup helper output fd");
+ data->out = xfdopen(duped, "r");
+
write_constant(helper->in, "capabilities\n");
- data->out = xfdopen(helper->out, "r");
while (1) {
const char *capname;
int mandatory = 0;
@@ -174,6 +186,7 @@ static int disconnect_helper(struct transport *transport)
strbuf_addf(&buf, "\n");
sendline(data, &buf);
close(data->helper->in);
+ close(data->helper->out);
fclose(data->out);
finish_command(data->helper);
free((char *)data->helper->argv[0]);
@@ -594,5 +607,6 @@ int transport_helper_init(struct transport *transport, const char *name)
transport->fetch = fetch;
transport->push_refs = push_refs;
transport->disconnect = release_helper;
+ transport->smart_options = &(data->gitoptions);
return 0;
}
diff --git a/transport.c b/transport.c
index b3e22ec..c4ecec4 100644
--- a/transport.c
+++ b/transport.c
@@ -398,6 +398,7 @@ struct git_transport_data {
struct git_transport_options options;
struct child_process *conn;
int fd[2];
+ unsigned got_remote_heads : 1;
struct extra_have_objects extra_have;
};
@@ -432,10 +433,15 @@ static int set_git_option(struct git_transport_options *opts,
static int connect_setup(struct transport *transport, int for_push, int verbose)
{
struct git_transport_data *data = transport->data;
+
+ if (data->conn)
+ return 0;
+
data->conn = git_connect(data->fd, transport->url,
for_push ? data->options.receivepack :
data->options.uploadpack,
verbose ? CONNECT_VERBOSE : 0);
+
return 0;
}
@@ -447,6 +453,7 @@ static struct ref *get_refs_via_connect(struct transport *transport, int for_pus
connect_setup(transport, for_push, 0);
get_remote_heads(data->fd[0], &refs, 0, NULL,
for_push ? REF_NORMAL : 0, &data->extra_have);
+ data->got_remote_heads = 1;
return refs;
}
@@ -477,9 +484,10 @@ static int fetch_refs_via_pack(struct transport *transport,
for (i = 0; i < nr_heads; i++)
origh[i] = heads[i] = xstrdup(to_fetch[i]->name);
- if (!data->conn) {
+ if (!data->got_remote_heads) {
connect_setup(transport, 0, 0);
get_remote_heads(data->fd[0], &refs_tmp, 0, NULL, 0, NULL);
+ data->got_remote_heads = 1;
}
refs = fetch_pack(&args, data->fd, data->conn,
@@ -490,6 +498,7 @@ static int fetch_refs_via_pack(struct transport *transport,
if (finish_connect(data->conn))
refs = NULL;
data->conn = NULL;
+ data->got_remote_heads = 0;
free_refs(refs_tmp);
@@ -718,12 +727,13 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re
struct send_pack_args args;
int ret;
- if (!data->conn) {
+ if (!data->got_remote_heads) {
struct ref *tmp_refs;
connect_setup(transport, 1, 0);
get_remote_heads(data->fd[0], &tmp_refs, 0, NULL, REF_NORMAL,
NULL);
+ data->got_remote_heads = 1;
}
memset(&args, 0, sizeof(args));
@@ -741,6 +751,7 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re
close(data->fd[0]);
ret |= finish_connect(data->conn);
data->conn = NULL;
+ data->got_remote_heads = 0;
return ret;
}
@@ -749,7 +760,8 @@ static int disconnect_git(struct transport *transport)
{
struct git_transport_data *data = transport->data;
if (data->conn) {
- packet_flush(data->fd[1]);
+ if (data->got_remote_heads)
+ packet_flush(data->fd[1]);
close(data->fd[0]);
close(data->fd[1]);
finish_connect(data->conn);
@@ -759,6 +771,32 @@ static int disconnect_git(struct transport *transport)
return 0;
}
+void transport_take_over(struct transport *transport,
+ struct child_process *child)
+{
+ struct git_transport_data *data;
+
+ if (!transport->smart_options)
+ die("Bug detected: Taking over transport requires non-NULL "
+ "smart_options field.");
+
+ data = xcalloc(1, sizeof(*data));
+ data->options = *transport->smart_options;
+ data->conn = child;
+ data->fd[0] = data->conn->out;
+ data->fd[1] = data->conn->in;
+ data->got_remote_heads = 0;
+ transport->data = data;
+
+ transport->set_option = NULL;
+ transport->get_refs_list = get_refs_via_connect;
+ transport->fetch = fetch_refs_via_pack;
+ transport->push = NULL;
+ transport->push_refs = git_transport_push;
+ transport->disconnect = disconnect_git;
+ transport->smart_options = &(data->options);
+}
+
static int is_local(const char *url)
{
const char *colon = strchr(url, ':');
@@ -881,6 +919,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
ret->smart_options = &(data->options);
data->conn = NULL;
+ data->got_remote_heads = 0;
} else if (!prefixcmp(url, "http://")
|| !prefixcmp(url, "https://")
|| !prefixcmp(url, "ftp://")) {
@@ -941,9 +980,9 @@ int transport_push(struct transport *transport,
*nonfastforward = 0;
verify_remote_names(refspec_nr, refspec);
- if (transport->push)
+ if (transport->push) {
return transport->push(transport, refspec_nr, refspec, flags);
- if (transport->push_refs) {
+ } else if (transport->push_refs) {
struct ref *remote_refs =
transport->get_refs_list(transport, 1);
struct ref *local_refs = get_local_heads();
@@ -987,6 +1026,7 @@ const struct ref *transport_get_remote_refs(struct transport *transport)
{
if (!transport->remote_refs)
transport->remote_refs = transport->get_refs_list(transport, 0);
+
return transport->remote_refs;
}
@@ -1021,6 +1061,7 @@ int transport_fetch_refs(struct transport *transport, struct ref *refs)
}
rc = transport->fetch(transport, nr_heads, heads);
+
free(heads);
return rc;
}
diff --git a/transport.h b/transport.h
index e90c285..781db2e 100644
--- a/transport.h
+++ b/transport.h
@@ -130,6 +130,8 @@ int transport_fetch_refs(struct transport *transport, struct ref *refs);
void transport_unlock_pack(struct transport *transport);
int transport_disconnect(struct transport *transport);
char *transport_anonymize_url(const char *url);
+void transport_take_over(struct transport *transport,
+ struct child_process *child);
/* Transport methods defined outside transport.c */
int transport_helper_init(struct transport *transport, const char *name);
--
1.6.6.rc1.300.gfbc27
^ permalink raw reply related
* [REROLL PATCH 7/8] Support remote archive from external protocol helpers
From: Ilari Liusvaara @ 2009-12-08 13:16 UTC (permalink / raw)
To: git
In-Reply-To: <1260278177-9029-1-git-send-email-ilari.liusvaara@elisanet.fi>
Helpers which support connect also should support remote archive
snapshot (or at least there's only one way to attempt it). So support
remote snapshotting for protocol helpers.
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
builtin-archive.c | 17 ++++++++++-------
transport-helper.c | 19 +++++++++++++++++++
transport.c | 21 +++++++++++++++++++++
transport.h | 5 +++++
4 files changed, 55 insertions(+), 7 deletions(-)
diff --git a/builtin-archive.c b/builtin-archive.c
index 12351e9..d34b3fd 100644
--- a/builtin-archive.c
+++ b/builtin-archive.c
@@ -5,6 +5,7 @@
#include "cache.h"
#include "builtin.h"
#include "archive.h"
+#include "transport.h"
#include "parse-options.h"
#include "pkt-line.h"
#include "sideband.h"
@@ -25,12 +26,16 @@ static void create_output_file(const char *output_file)
static int run_remote_archiver(int argc, const char **argv,
const char *remote, const char *exec)
{
- char *url, buf[LARGE_PACKET_MAX];
+ char buf[LARGE_PACKET_MAX];
int fd[2], i, len, rv;
- struct child_process *conn;
+ struct transport *transport;
+ struct remote *_remote;
- url = xstrdup(remote);
- conn = git_connect(fd, url, exec, 0);
+ _remote = remote_get(remote);
+ if (!_remote->url[0])
+ die("git archive: Remote with no URL");
+ transport = transport_get(_remote, _remote->url[0]);
+ transport_connect(transport, "git-upload-archive", exec, fd);
for (i = 1; i < argc; i++)
packet_write(fd[1], "argument %s\n", argv[i]);
@@ -53,9 +58,7 @@ static int run_remote_archiver(int argc, const char **argv,
/* Now, start reading from fd[0] and spit it out to stdout */
rv = recv_sideband("archive", fd[0], 1);
- close(fd[0]);
- close(fd[1]);
- rv |= finish_connect(conn);
+ rv |= transport_disconnect(transport);
return !!rv;
}
diff --git a/transport-helper.c b/transport-helper.c
index e30c914..70c798e 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -477,6 +477,24 @@ static int process_connect(struct transport *transport,
return _process_connect(transport, name, exec);
}
+static int connect_helper(struct transport *transport, const char *name,
+ const char *exec, int fd[2])
+{
+ struct helper_data *data = transport->data;
+
+ /* Get_helper so connect is inited. */
+ get_helper(transport);
+ if (!data->connect)
+ die("Operation not supported by protocol.");
+
+ if (!_process_connect(transport, name, exec))
+ die("Can't connect to subservice %s.", name);
+
+ fd[0] = data->helper->out;
+ fd[1] = data->helper->in;
+ return 0;
+}
+
static int fetch(struct transport *transport,
int nr_heads, struct ref **to_fetch)
{
@@ -721,6 +739,7 @@ int transport_helper_init(struct transport *transport, const char *name)
transport->fetch = fetch;
transport->push_refs = push_refs;
transport->disconnect = release_helper;
+ transport->connect = connect_helper;
transport->smart_options = &(data->gitoptions);
return 0;
}
diff --git a/transport.c b/transport.c
index c4ecec4..64938fd 100644
--- a/transport.c
+++ b/transport.c
@@ -756,6 +756,17 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re
return ret;
}
+static int connect_git(struct transport *transport, const char *name,
+ const char *executable, int fd[2])
+{
+ struct git_transport_data *data = transport->data;
+ data->conn = git_connect(data->fd, transport->url,
+ executable, 0);
+ fd[0] = data->fd[0];
+ fd[1] = data->fd[1];
+ return 0;
+}
+
static int disconnect_git(struct transport *transport)
{
struct git_transport_data *data = transport->data;
@@ -915,6 +926,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
ret->get_refs_list = get_refs_via_connect;
ret->fetch = fetch_refs_via_pack;
ret->push_refs = git_transport_push;
+ ret->connect = connect_git;
ret->disconnect = disconnect_git;
ret->smart_options = &(data->options);
@@ -1075,6 +1087,15 @@ void transport_unlock_pack(struct transport *transport)
}
}
+int transport_connect(struct transport *transport, const char *name,
+ const char *exec, int fd[2])
+{
+ if (transport->connect)
+ return transport->connect(transport, name, exec, fd);
+ else
+ die("Operation not supported by protocol");
+}
+
int transport_disconnect(struct transport *transport)
{
int ret = 0;
diff --git a/transport.h b/transport.h
index 781db2e..97ba251 100644
--- a/transport.h
+++ b/transport.h
@@ -64,6 +64,8 @@ struct transport {
**/
int (*push_refs)(struct transport *transport, struct ref *refs, int flags);
int (*push)(struct transport *connection, int refspec_nr, const char **refspec, int flags);
+ int (*connect)(struct transport *connection, const char *name,
+ const char *executable, int fd[2]);
/** get_refs_list(), fetch(), and push_refs() can keep
* resources (such as a connection) reserved for futher
@@ -133,6 +135,9 @@ char *transport_anonymize_url(const char *url);
void transport_take_over(struct transport *transport,
struct child_process *child);
+int transport_connect(struct transport *transport, const char *name,
+ const char *exec, int fd[2]);
+
/* Transport methods defined outside transport.c */
int transport_helper_init(struct transport *transport, const char *name);
--
1.6.6.rc1.300.gfbc27
^ permalink raw reply related
* [REROLL PATCH 6/8] Support remote helpers implementing smart transports
From: Ilari Liusvaara @ 2009-12-08 13:16 UTC (permalink / raw)
To: git
In-Reply-To: <1260278177-9029-1-git-send-email-ilari.liusvaara@elisanet.fi>
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
Documentation/git-remote-helpers.txt | 25 +++++++-
transport-helper.c | 126 ++++++++++++++++++++++++++++++++--
2 files changed, 144 insertions(+), 7 deletions(-)
diff --git a/Documentation/git-remote-helpers.txt b/Documentation/git-remote-helpers.txt
index 20a05fe..b957813 100644
--- a/Documentation/git-remote-helpers.txt
+++ b/Documentation/git-remote-helpers.txt
@@ -93,6 +93,20 @@ Supported if the helper has the "push" capability.
+
Supported if the helper has the "import" capability.
+'connect' <service>::
+ Connects to given service. Stdin and stdout of helper are
+ connected to specified service (git prefix is included in service
+ name so e.g. fetching uses 'git-upload-pack' as service) on
+ remote side. Valid replies to this command are empty line
+ (connection established), 'fallback' (no smart transport support,
+ fall back to dumb transports) and just exiting with error message
+ printed (can't connect, don't bother trying to fall back). After
+ line feed terminating the positive (empty) response, the output
+ of service starts. After the connection ends, the remote
+ helper exits.
++
+Supported if the helper has the "connect" capability.
+
If a fatal error occurs, the program writes the error message to
stderr and exits. The caller should expect that a suitable error
message has been printed if the child closes the connection without
@@ -126,6 +140,9 @@ CAPABILITIES
all, it must cover all refs reported by the list command; if
it is not used, it is effectively "*:*"
+'connect'::
+ This helper supports the 'connect' command.
+
REF LIST ATTRIBUTES
-------------------
@@ -168,9 +185,15 @@ OPTIONS
but don't actually change any repository data. For most
helpers this only applies to the 'push', if supported.
+'option servpath <c-style-quoted-path>'::
+ Set service path (--upload-pack, --receive-pack etc.) for
+ next connect. Remote helper MAY support this option. Remote
+ helper MUST NOT rely on this option being set before
+ connect request occurs.
+
Documentation
-------------
-Documentation by Daniel Barkalow.
+Documentation by Daniel Barkalow and Ilari Liusvaara
GIT
---
diff --git a/transport-helper.c b/transport-helper.c
index 3b7340c..e30c914 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -18,7 +18,9 @@ struct helper_data
unsigned fetch : 1,
import : 1,
option : 1,
- push : 1;
+ push : 1,
+ connect : 1,
+ no_disconnect_req : 1;
/* These go from remote name (as in "list") to private name */
struct refspec *refspecs;
int refspec_nr;
@@ -34,12 +36,12 @@ static void sendline(struct helper_data *helper, struct strbuf *buffer)
die_errno("Full write to remote helper failed");
}
-static int recvline(struct helper_data *helper, struct strbuf *buffer)
+static int _recvline(FILE *helper, struct strbuf *buffer)
{
strbuf_reset(buffer);
if (debug)
fprintf(stderr, "Debug: Remote helper: Waiting...\n");
- if (strbuf_getline(buffer, helper->out, '\n') == EOF) {
+ if (strbuf_getline(buffer, helper, '\n') == EOF) {
if (debug)
fprintf(stderr, "Debug: Remote helper quit.\n");
exit(128);
@@ -50,6 +52,11 @@ static int recvline(struct helper_data *helper, struct strbuf *buffer)
return 0;
}
+static int recvline(struct helper_data *helper, struct strbuf *buffer)
+{
+ return _recvline(helper->out, buffer);
+}
+
static void xchgline(struct helper_data *helper, struct strbuf *buffer)
{
sendline(helper, buffer);
@@ -84,6 +91,15 @@ const char *remove_ext_force(const char *url)
return url;
}
+static void do_take_over(struct transport *transport)
+{
+ struct helper_data *data;
+ data = (struct helper_data*)transport->data;
+ transport_take_over(transport, data->helper);
+ fclose(data->out);
+ free(data);
+}
+
static struct child_process *get_helper(struct transport *transport)
{
struct helper_data *data = transport->data;
@@ -110,12 +126,12 @@ static struct child_process *get_helper(struct transport *transport)
if (start_command(helper))
die("Unable to run helper: git %s", helper->argv[0]);
data->helper = helper;
+ data->no_disconnect_req = 0;
/*
* Open the output as FILE* so strbuf_getline() can be used.
* Do this with duped fd because fclose() will close the fd,
* and stuff like taking over will require the fd to remain.
- *
*/
duped = dup(helper->out);
if (duped < 0)
@@ -153,6 +169,8 @@ static struct child_process *get_helper(struct transport *transport)
refspec_nr + 1,
refspec_alloc);
refspecs[refspec_nr++] = strdup(buf.buf + strlen("refspec "));
+ } else if (!strcmp(capname, "connect")) {
+ data->connect = 1;
} else if (mandatory) {
fflush(stderr);
die("Unknown madatory capability %s. This remote "
@@ -183,8 +201,10 @@ static int disconnect_helper(struct transport *transport)
if (data->helper) {
if (debug)
fprintf(stderr, "Debug: Disconnecting.\n");
- strbuf_addf(&buf, "\n");
- sendline(data, &buf);
+ if(!data->no_disconnect_req) {
+ strbuf_addf(&buf, "\n");
+ sendline(data, &buf);
+ }
close(data->helper->in);
close(data->helper->out);
fclose(data->out);
@@ -378,12 +398,96 @@ static int fetch_with_import(struct transport *transport,
return 0;
}
+static int _process_connect(struct transport *transport,
+ const char *name, const char *exec)
+{
+ struct helper_data *data = transport->data;
+ struct strbuf cmdbuf = STRBUF_INIT;
+ struct child_process *helper;
+ int r, duped, ret = 0;
+ FILE *input;
+
+ helper = get_helper(transport);
+
+ /*
+ * Yes, dup the pipe another time, as we need unbuffered version
+ * of input pipe as FILE*. fclose() closes the underlying fd and
+ * stream buffering only can be changed before first I/O operation
+ * on it.
+ */
+ duped = dup(helper->out);
+ if (duped < 0)
+ die_errno("Can't dup helper output fd");
+ input = xfdopen(duped, "r");
+ setvbuf(input, NULL, _IONBF, 0);
+
+ /*
+ * Handle --upload-pack and friends. This is fire and forget...
+ * just warn if it fails.
+ */
+ if (strcmp(name, exec)) {
+ r = set_helper_option(transport, "servpath", exec);
+ if (r > 0)
+ fprintf(stderr, "Warning: Setting remote service path "
+ "not supported by protocol.\n");
+ else if (r < 0)
+ fprintf(stderr, "Warning: Invalid remote service "
+ "path.\n");
+ }
+
+ if (data->connect)
+ strbuf_addf(&cmdbuf, "connect %s\n", name);
+ else
+ goto exit;
+
+ sendline(data, &cmdbuf);
+ _recvline(input, &cmdbuf);
+ if (!strcmp(cmdbuf.buf, "")) {
+ data->no_disconnect_req = 1;
+ if (debug)
+ fprintf(stderr, "Debug: Smart transport connection "
+ "ready.\n");
+ ret = 1;
+ } else if (!strcmp(cmdbuf.buf, "fallback")) {
+ if (debug)
+ fprintf(stderr, "Debug: Falling back to dumb "
+ "transport.\n");
+ } else
+ die("Unknown response to connect: %s",
+ cmdbuf.buf);
+
+exit:
+ fclose(input);
+ return ret;
+}
+
+static int process_connect(struct transport *transport,
+ int for_push)
+{
+ struct helper_data *data = transport->data;
+ const char *name;
+ const char *exec;
+
+ name = for_push ? "git-receive-pack" : "git-upload-pack";
+ if (for_push)
+ exec = data->gitoptions.receivepack;
+ else
+ exec = data->gitoptions.uploadpack;
+
+ return _process_connect(transport, name, exec);
+}
+
static int fetch(struct transport *transport,
int nr_heads, struct ref **to_fetch)
{
struct helper_data *data = transport->data;
int i, count;
+ if (process_connect(transport, 0)) {
+ do_take_over(transport);
+ return transport->fetch(transport, nr_heads, to_fetch);
+ }
+
count = 0;
for (i = 0; i < nr_heads; i++)
if (!(to_fetch[i]->status & REF_STATUS_UPTODATE))
@@ -411,6 +515,11 @@ static int push_refs(struct transport *transport,
struct child_process *helper;
struct ref *ref;
+ if (process_connect(transport, 1)) {
+ do_take_over(transport);
+ return transport->push_refs(transport, remote_refs, flags);
+ }
+
if (!remote_refs)
return 0;
@@ -551,6 +660,11 @@ static struct ref *get_refs_list(struct transport *transport, int for_push)
helper = get_helper(transport);
+ if (process_connect(transport, for_push)) {
+ do_take_over(transport);
+ return transport->get_refs_list(transport, for_push);
+ }
+
if (data->push && for_push)
write_str_in_full(helper->in, "list for-push\n");
else
--
1.6.6.rc1.300.gfbc27
^ permalink raw reply related
* [REROLL PATCH 3/8] Pass unknown protocols to external protocol handlers
From: Ilari Liusvaara @ 2009-12-08 13:16 UTC (permalink / raw)
To: git
In-Reply-To: <1260278177-9029-1-git-send-email-ilari.liusvaara@elisanet.fi>
Change URL handling to allow external protocol handlers to implement
new protocols without the '::' syntax if helper name does not conflict
with any built-in protocol.
foo:// now invokes git-remote-foo with foo:// URL.
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
transport-helper.c | 22 ++++++++++++-
transport.c | 90 +++++++++++++++++++++++++++++++++++++++++++---------
2 files changed, 96 insertions(+), 16 deletions(-)
diff --git a/transport-helper.c b/transport-helper.c
index f977d28..0e82553 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -63,6 +63,26 @@ static void write_constant(int fd, const char *str)
die_errno("Full write to remote helper failed");
}
+const char *remove_ext_force(const char *url)
+{
+ const char *url2 = url;
+ const char *first_colon = NULL;
+
+ if (!url)
+ return NULL;
+
+ while (*url2 && !first_colon)
+ if (*url2 == ':')
+ first_colon = url2;
+ else
+ url2++;
+
+ if (first_colon && first_colon[1] == ':')
+ return first_colon + 2;
+ else
+ return url;
+}
+
static struct child_process *get_helper(struct transport *transport)
{
struct helper_data *data = transport->data;
@@ -83,7 +103,7 @@ static struct child_process *get_helper(struct transport *transport)
strbuf_addf(&buf, "remote-%s", data->name);
helper->argv[0] = strbuf_detach(&buf, NULL);
helper->argv[1] = transport->remote->name;
- helper->argv[2] = transport->url;
+ helper->argv[2] = remove_ext_force(transport->url);
helper->git_cmd = 1;
if (start_command(helper))
die("Unable to run helper: git %s", helper->argv[0]);
diff --git a/transport.c b/transport.c
index 3eea836..e42a82b 100644
--- a/transport.c
+++ b/transport.c
@@ -780,6 +780,58 @@ static int is_file(const char *url)
return S_ISREG(buf.st_mode);
}
+static const char *strchrc(const char *str, int c)
+{
+ while (*str)
+ if (*str == c)
+ return str;
+ else
+ str++;
+ return NULL;
+}
+
+static int is_url(const char *url)
+{
+ const char *url2, *first_slash;
+
+ if (!url)
+ return 0;
+ url2 = url;
+ first_slash = strchrc(url, '/');
+
+ /* Input with no slash at all or slash first can't be URL. */
+ if (!first_slash || first_slash == url)
+ return 0;
+ /* Character before must be : and next must be /. */
+ if (first_slash[-1] != ':' || first_slash[1] != '/')
+ return 0;
+ /* There must be something before the :// */
+ if (first_slash == url + 1)
+ return 0;
+ /*
+ * Check all characters up to first slash. Only alpha, num and
+ * colon (":") are allowed. ":" must be followed by ":" or "/".
+ */
+ url2 = url;
+ while (url2 < first_slash) {
+ if (*url2 != ':' && !isalnum((unsigned char)*url2))
+ return 0;
+ if (*url2 == ':' && url2[1] != ':' && url2[1] != '/')
+ return 0;
+ if (*url2 == ':')
+ url2++; /* Skip second : */
+ url2++;
+ }
+
+ /* Valid enough. */
+ return 1;
+}
+
+static int external_specification_len(const char *url)
+{
+ return strchrc(url, ':') - url;
+}
+
struct transport *transport_get(struct remote *remote, const char *url)
{
struct transport *ret = xcalloc(1, sizeof(*ret));
@@ -805,30 +857,23 @@ struct transport *transport_get(struct remote *remote, const char *url)
if (remote && remote->foreign_vcs) {
transport_helper_init(ret, remote->foreign_vcs);
- return ret;
- }
-
- if (!prefixcmp(url, "rsync:")) {
+ } else if (!prefixcmp(url, "rsync:")) {
ret->get_refs_list = get_refs_via_rsync;
ret->fetch = fetch_objs_via_rsync;
ret->push = rsync_transport_push;
-
- } else if (!prefixcmp(url, "http://")
- || !prefixcmp(url, "https://")
- || !prefixcmp(url, "ftp://")) {
- transport_helper_init(ret, "curl");
-#ifdef NO_CURL
- error("git was compiled without libcurl support.");
-#endif
-
} else if (is_local(url) && is_file(url)) {
struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
ret->data = data;
ret->get_refs_list = get_refs_from_bundle;
ret->fetch = fetch_refs_from_bundle;
ret->disconnect = close_bundle;
-
- } else {
+ } else if (!is_url(url)
+ || !prefixcmp(url, "file://")
+ || !prefixcmp(url, "git://")
+ || !prefixcmp(url, "ssh://")
+ || !prefixcmp(url, "git+ssh://")
+ || !prefixcmp(url, "ssh+git://")) {
+ /* These are builtin smart transports. */
struct git_transport_data *data = xcalloc(1, sizeof(*data));
ret->data = data;
ret->set_option = set_git_option;
@@ -845,6 +890,21 @@ struct transport *transport_get(struct remote *remote, const char *url)
data->receivepack = "git-receive-pack";
if (remote->receivepack)
data->receivepack = remote->receivepack;
+ } else if (!prefixcmp(url, "http://")
+ || !prefixcmp(url, "https://")
+ || !prefixcmp(url, "ftp://")) {
+ /* These three are just plain special. */
+ transport_helper_init(ret, "curl");
+#ifdef NO_CURL
+ error("git was compiled without libcurl support.");
+#endif
+ } else {
+ /* Unknown protocol in URL. Pass to external handler. */
+ int len = external_specification_len(url);
+ char *handler = xmalloc(len + 1);
+ handler[len] = 0;
+ strncpy(handler, url, len);
+ transport_helper_init(ret, handler);
}
return ret;
--
1.6.6.rc1.300.gfbc27
^ permalink raw reply related
* [REROLL PATCH 4/8] Refactor git transport options parsing
From: Ilari Liusvaara @ 2009-12-08 13:16 UTC (permalink / raw)
To: git
In-Reply-To: <1260278177-9029-1-git-send-email-ilari.liusvaara@elisanet.fi>
Refactor the transport options parsing so that protocols that aren't
directly smart transports (file://, git://, ssh:// & co) can record
the smart transport options for the case if it turns that transport
can actually be smart.
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
transport.c | 78 +++++++++++++++++++++++++++++++++++-----------------------
transport.h | 15 +++++++++++
2 files changed, 62 insertions(+), 31 deletions(-)
diff --git a/transport.c b/transport.c
index e42a82b..b3e22ec 100644
--- a/transport.c
+++ b/transport.c
@@ -395,41 +395,35 @@ static int close_bundle(struct transport *transport)
}
struct git_transport_data {
- unsigned thin : 1;
- unsigned keep : 1;
- unsigned followtags : 1;
- int depth;
+ struct git_transport_options options;
struct child_process *conn;
int fd[2];
- const char *uploadpack;
- const char *receivepack;
struct extra_have_objects extra_have;
};
-static int set_git_option(struct transport *connection,
+static int set_git_option(struct git_transport_options *opts,
const char *name, const char *value)
{
- struct git_transport_data *data = connection->data;
if (!strcmp(name, TRANS_OPT_UPLOADPACK)) {
- data->uploadpack = value;
+ opts->uploadpack = value;
return 0;
} else if (!strcmp(name, TRANS_OPT_RECEIVEPACK)) {
- data->receivepack = value;
+ opts->receivepack = value;
return 0;
} else if (!strcmp(name, TRANS_OPT_THIN)) {
- data->thin = !!value;
+ opts->thin = !!value;
return 0;
} else if (!strcmp(name, TRANS_OPT_FOLLOWTAGS)) {
- data->followtags = !!value;
+ opts->followtags = !!value;
return 0;
} else if (!strcmp(name, TRANS_OPT_KEEP)) {
- data->keep = !!value;
+ opts->keep = !!value;
return 0;
} else if (!strcmp(name, TRANS_OPT_DEPTH)) {
if (!value)
- data->depth = 0;
+ opts->depth = 0;
else
- data->depth = atoi(value);
+ opts->depth = atoi(value);
return 0;
}
return 1;
@@ -439,7 +433,8 @@ static int connect_setup(struct transport *transport, int for_push, int verbose)
{
struct git_transport_data *data = transport->data;
data->conn = git_connect(data->fd, transport->url,
- for_push ? data->receivepack : data->uploadpack,
+ for_push ? data->options.receivepack :
+ data->options.uploadpack,
verbose ? CONNECT_VERBOSE : 0);
return 0;
}
@@ -469,15 +464,15 @@ static int fetch_refs_via_pack(struct transport *transport,
struct ref *refs_tmp = NULL;
memset(&args, 0, sizeof(args));
- args.uploadpack = data->uploadpack;
- args.keep_pack = data->keep;
+ args.uploadpack = data->options.uploadpack;
+ args.keep_pack = data->options.keep;
args.lock_pack = 1;
- args.use_thin_pack = data->thin;
- args.include_tag = data->followtags;
+ args.use_thin_pack = data->options.thin;
+ args.include_tag = data->options.followtags;
args.verbose = (transport->verbose > 0);
args.quiet = (transport->verbose < 0);
args.no_progress = args.quiet || (!transport->progress && !isatty(1));
- args.depth = data->depth;
+ args.depth = data->options.depth;
for (i = 0; i < nr_heads; i++)
origh[i] = heads[i] = xstrdup(to_fetch[i]->name);
@@ -734,7 +729,7 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re
memset(&args, 0, sizeof(args));
args.send_mirror = !!(flags & TRANSPORT_PUSH_MIRROR);
args.force_update = !!(flags & TRANSPORT_PUSH_FORCE);
- args.use_thin_pack = data->thin;
+ args.use_thin_pack = data->options.thin;
args.verbose = !!(flags & TRANSPORT_PUSH_VERBOSE);
args.quiet = !!(flags & TRANSPORT_PUSH_QUIET);
args.dry_run = !!(flags & TRANSPORT_PUSH_DRY_RUN);
@@ -861,12 +856,14 @@ struct transport *transport_get(struct remote *remote, const char *url)
ret->get_refs_list = get_refs_via_rsync;
ret->fetch = fetch_objs_via_rsync;
ret->push = rsync_transport_push;
+ ret->smart_options = NULL;
} else if (is_local(url) && is_file(url)) {
struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
ret->data = data;
ret->get_refs_list = get_refs_from_bundle;
ret->fetch = fetch_refs_from_bundle;
ret->disconnect = close_bundle;
+ ret->smart_options = NULL;
} else if (!is_url(url)
|| !prefixcmp(url, "file://")
|| !prefixcmp(url, "git://")
@@ -876,20 +873,14 @@ struct transport *transport_get(struct remote *remote, const char *url)
/* These are builtin smart transports. */
struct git_transport_data *data = xcalloc(1, sizeof(*data));
ret->data = data;
- ret->set_option = set_git_option;
+ ret->set_option = NULL;
ret->get_refs_list = get_refs_via_connect;
ret->fetch = fetch_refs_via_pack;
ret->push_refs = git_transport_push;
ret->disconnect = disconnect_git;
+ ret->smart_options = &(data->options);
- data->thin = 1;
data->conn = NULL;
- data->uploadpack = "git-upload-pack";
- if (remote->uploadpack)
- data->uploadpack = remote->uploadpack;
- data->receivepack = "git-receive-pack";
- if (remote->receivepack)
- data->receivepack = remote->receivepack;
} else if (!prefixcmp(url, "http://")
|| !prefixcmp(url, "https://")
|| !prefixcmp(url, "ftp://")) {
@@ -907,14 +898,39 @@ struct transport *transport_get(struct remote *remote, const char *url)
transport_helper_init(ret, handler);
}
+ if (ret->smart_options) {
+ ret->smart_options->thin = 1;
+ ret->smart_options->uploadpack = "git-upload-pack";
+ if (remote->uploadpack)
+ ret->smart_options->uploadpack = remote->uploadpack;
+ ret->smart_options->receivepack = "git-receive-pack";
+ if (remote->receivepack)
+ ret->smart_options->receivepack = remote->receivepack;
+ }
+
return ret;
}
int transport_set_option(struct transport *transport,
const char *name, const char *value)
{
+ int git_reports = 1, protocol_reports = 1;
+
+ if (transport->smart_options)
+ git_reports = set_git_option(transport->smart_options,
+ name, value);
+
if (transport->set_option)
- return transport->set_option(transport, name, value);
+ protocol_reports = transport->set_option(transport, name,
+ value);
+
+ /* If either report is 0, report 0 (success). */
+ if (!git_reports || !protocol_reports)
+ return 0;
+ /* If either reports -1 (invalid value), report -1. */
+ if ((git_reports == -1) || (protocol_reports == -1))
+ return -1;
+ /* Otherwise if both report unknown, report unknown. */
return 1;
}
diff --git a/transport.h b/transport.h
index 9e74406..e90c285 100644
--- a/transport.h
+++ b/transport.h
@@ -4,6 +4,15 @@
#include "cache.h"
#include "remote.h"
+struct git_transport_options {
+ unsigned thin : 1;
+ unsigned keep : 1;
+ unsigned followtags : 1;
+ int depth;
+ const char *uploadpack;
+ const char *receivepack;
+};
+
struct transport {
struct remote *remote;
const char *url;
@@ -65,6 +74,12 @@ struct transport {
signed verbose : 3;
/* Force progress even if the output is not a tty */
unsigned progress : 1;
+ /*
+ * If transport is at least potentially smart, this points to
+ * git_transport_options structure to use in case transport
+ * actually turns out to be smart.
+ */
+ struct git_transport_options *smart_options;
};
#define TRANSPORT_PUSH_ALL 1
--
1.6.6.rc1.300.gfbc27
^ permalink raw reply related
* [REROLL PATCH 1/8] Add remote helper debug mode
From: Ilari Liusvaara @ 2009-12-08 13:16 UTC (permalink / raw)
To: git
In-Reply-To: <1260278177-9029-1-git-send-email-ilari.liusvaara@elisanet.fi>
Remote helpers deadlock easily, so support debug mode which shows the
interaction steps.
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
transport-helper.c | 94 ++++++++++++++++++++++++++++++++++++++--------------
1 files changed, 69 insertions(+), 25 deletions(-)
diff --git a/transport-helper.c b/transport-helper.c
index 11f3d7e..a721dc2 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -8,6 +8,8 @@
#include "quote.h"
#include "remote.h"
+static int debug;
+
struct helper_data
{
const char *name;
@@ -22,6 +24,45 @@ struct helper_data
int refspec_nr;
};
+static void sendline(struct helper_data *helper, struct strbuf *buffer)
+{
+ if (debug)
+ fprintf(stderr, "Debug: Remote helper: -> %s", buffer->buf);
+ if (write_in_full(helper->helper->in, buffer->buf, buffer->len)
+ != buffer->len)
+ die_errno("Full write to remote helper failed");
+}
+
+static int recvline(struct helper_data *helper, struct strbuf *buffer)
+{
+ strbuf_reset(buffer);
+ if (debug)
+ fprintf(stderr, "Debug: Remote helper: Waiting...\n");
+ if (strbuf_getline(buffer, helper->out, '\n') == EOF) {
+ if (debug)
+ fprintf(stderr, "Debug: Remote helper quit.\n");
+ exit(128);
+ }
+
+ if (debug)
+ fprintf(stderr, "Debug: Remote helper: <- %s\n", buffer->buf);
+ return 0;
+}
+
+static void xchgline(struct helper_data *helper, struct strbuf *buffer)
+{
+ sendline(helper, buffer);
+ recvline(helper, buffer);
+}
+
+static void write_constant(int fd, const char *str)
+{
+ if (debug)
+ fprintf(stderr, "Debug: Remote helper: -> %s", str);
+ if (write_in_full(fd, str, strlen(str)) != strlen(str))
+ die_errno("Full write to remote helper failed");
+}
+
static struct child_process *get_helper(struct transport *transport)
{
struct helper_data *data = transport->data;
@@ -48,15 +89,16 @@ static struct child_process *get_helper(struct transport *transport)
die("Unable to run helper: git %s", helper->argv[0]);
data->helper = helper;
- write_str_in_full(helper->in, "capabilities\n");
+ write_constant(helper->in, "capabilities\n");
data->out = xfdopen(helper->out, "r");
while (1) {
- if (strbuf_getline(&buf, data->out, '\n') == EOF)
- exit(128); /* child died, message supplied already */
+ recvline(data, &buf);
if (!*buf.buf)
break;
+ if (debug)
+ fprintf(stderr, "Debug: Got cap %s\n", buf.buf);
if (!strcmp(buf.buf, "fetch"))
data->fetch = 1;
if (!strcmp(buf.buf, "option"))
@@ -82,14 +124,21 @@ static struct child_process *get_helper(struct transport *transport)
free(refspecs);
}
strbuf_release(&buf);
+ if (debug)
+ fprintf(stderr, "Debug: Capabilities complete.\n");
return data->helper;
}
static int disconnect_helper(struct transport *transport)
{
struct helper_data *data = transport->data;
+ struct strbuf buf = STRBUF_INIT;
+
if (data->helper) {
- write_str_in_full(data->helper->in, "\n");
+ if (debug)
+ fprintf(stderr, "Debug: Disconnecting.\n");
+ strbuf_addf(&buf, "\n");
+ sendline(data, &buf);
close(data->helper->in);
fclose(data->out);
finish_command(data->helper);
@@ -117,10 +166,11 @@ static int set_helper_option(struct transport *transport,
const char *name, const char *value)
{
struct helper_data *data = transport->data;
- struct child_process *helper = get_helper(transport);
struct strbuf buf = STRBUF_INIT;
int i, ret, is_bool = 0;
+ get_helper(transport);
+
if (!data->option)
return 1;
@@ -143,12 +193,7 @@ static int set_helper_option(struct transport *transport,
quote_c_style(value, &buf, NULL, 0);
strbuf_addch(&buf, '\n');
- if (write_in_full(helper->in, buf.buf, buf.len) != buf.len)
- die_errno("cannot send option to %s", data->name);
-
- strbuf_reset(&buf);
- if (strbuf_getline(&buf, data->out, '\n') == EOF)
- exit(128); /* child died, message supplied already */
+ xchgline(data, &buf);
if (!strcmp(buf.buf, "ok"))
ret = 0;
@@ -208,13 +253,10 @@ static int fetch_with_fetch(struct transport *transport,
}
strbuf_addch(&buf, '\n');
- if (write_in_full(data->helper->in, buf.buf, buf.len) != buf.len)
- die_errno("cannot send fetch to %s", data->name);
+ sendline(data, &buf);
while (1) {
- strbuf_reset(&buf);
- if (strbuf_getline(&buf, data->out, '\n') == EOF)
- exit(128); /* child died, message supplied already */
+ recvline(data, &buf);
if (!prefixcmp(buf.buf, "lock ")) {
const char *name = buf.buf + 5;
@@ -249,12 +291,13 @@ static int fetch_with_import(struct transport *transport,
int nr_heads, struct ref **to_fetch)
{
struct child_process fastimport;
- struct child_process *helper = get_helper(transport);
struct helper_data *data = transport->data;
int i;
struct ref *posn;
struct strbuf buf = STRBUF_INIT;
+ get_helper(transport);
+
if (get_importer(transport, &fastimport))
die("Couldn't run fast-import");
@@ -264,7 +307,7 @@ static int fetch_with_import(struct transport *transport,
continue;
strbuf_addf(&buf, "import %s\n", posn->name);
- write_in_full(helper->in, buf.buf, buf.len);
+ sendline(data, &buf);
strbuf_reset(&buf);
}
disconnect_helper(transport);
@@ -369,17 +412,14 @@ static int push_refs(struct transport *transport,
}
strbuf_addch(&buf, '\n');
- if (write_in_full(helper->in, buf.buf, buf.len) != buf.len)
- exit(128);
+ sendline(data, &buf);
ref = remote_refs;
while (1) {
char *refname, *msg;
int status;
- strbuf_reset(&buf);
- if (strbuf_getline(&buf, data->out, '\n') == EOF)
- exit(128); /* child died, message supplied already */
+ recvline(data, &buf);
if (!buf.len)
break;
@@ -471,8 +511,7 @@ static struct ref *get_refs_list(struct transport *transport, int for_push)
while (1) {
char *eov, *eon;
- if (strbuf_getline(&buf, data->out, '\n') == EOF)
- exit(128); /* child died, message supplied already */
+ recvline(data, &buf);
if (!*buf.buf)
break;
@@ -497,6 +536,8 @@ static struct ref *get_refs_list(struct transport *transport, int for_push)
}
tail = &((*tail)->next);
}
+ if (debug)
+ fprintf(stderr, "Debug: Read ref listing.\n");
strbuf_release(&buf);
for (posn = ret; posn; posn = posn->next)
@@ -510,6 +551,9 @@ int transport_helper_init(struct transport *transport, const char *name)
struct helper_data *data = xcalloc(sizeof(*data), 1);
data->name = name;
+ if (getenv("GIT_TRANSPORT_HELPER_DEBUG"))
+ debug = 1;
+
transport->data = data;
transport->set_option = set_helper_option;
transport->get_refs_list = get_refs_list;
--
1.6.6.rc1.300.gfbc27
^ permalink raw reply related
* [REROLL PATCH 2/8] Support mandatory capabilities
From: Ilari Liusvaara @ 2009-12-08 13:16 UTC (permalink / raw)
To: git
In-Reply-To: <1260278177-9029-1-git-send-email-ilari.liusvaara@elisanet.fi>
Add support for marking capability as mandatory for hosting git version
to understand. This is useful for helpers which require various types
of assistance from main git binary.
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
Documentation/git-remote-helpers.txt | 5 ++++-
transport-helper.c | 26 ++++++++++++++++++++------
2 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/Documentation/git-remote-helpers.txt b/Documentation/git-remote-helpers.txt
index 5cfdc0c..20a05fe 100644
--- a/Documentation/git-remote-helpers.txt
+++ b/Documentation/git-remote-helpers.txt
@@ -25,7 +25,10 @@ Commands are given by the caller on the helper's standard input, one per line.
'capabilities'::
Lists the capabilities of the helper, one per line, ending
- with a blank line.
+ with a blank line. Each capability may be preceeded with '*'.
+ This marks them mandatory for git version using the remote
+ helper to understand (unknown mandatory capability is fatal
+ error).
'list'::
Lists the refs, one per line, in the format "<value> <name>
diff --git a/transport-helper.c b/transport-helper.c
index a721dc2..f977d28 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -93,25 +93,39 @@ static struct child_process *get_helper(struct transport *transport)
data->out = xfdopen(helper->out, "r");
while (1) {
+ const char *capname;
+ int mandatory = 0;
recvline(data, &buf);
if (!*buf.buf)
break;
+
+ if (*buf.buf == '*') {
+ capname = buf.buf + 1;
+ mandatory = 1;
+ } else
+ capname = buf.buf;
+
if (debug)
- fprintf(stderr, "Debug: Got cap %s\n", buf.buf);
- if (!strcmp(buf.buf, "fetch"))
+ fprintf(stderr, "Debug: Got cap %s\n", capname);
+ if (!strcmp(capname, "fetch"))
data->fetch = 1;
- if (!strcmp(buf.buf, "option"))
+ else if (!strcmp(capname, "option"))
data->option = 1;
- if (!strcmp(buf.buf, "push"))
+ else if (!strcmp(capname, "push"))
data->push = 1;
- if (!strcmp(buf.buf, "import"))
+ else if (!strcmp(capname, "import"))
data->import = 1;
- if (!data->refspecs && !prefixcmp(buf.buf, "refspec ")) {
+ else if (!data->refspecs && !prefixcmp(capname, "refspec ")) {
ALLOC_GROW(refspecs,
refspec_nr + 1,
refspec_alloc);
refspecs[refspec_nr++] = strdup(buf.buf + strlen("refspec "));
+ } else if (mandatory) {
+ fflush(stderr);
+ die("Unknown madatory capability %s. This remote "
+ "helper probably needs newer version of Git.\n",
+ capname);
}
}
if (refspecs) {
--
1.6.6.rc1.300.gfbc27
^ permalink raw reply related
* [REROLL PATCH 0/8] Remote helpers smart transport extensions
From: Ilari Liusvaara @ 2009-12-08 13:16 UTC (permalink / raw)
To: git
This is rerolled version of remote helpers exensions. The changes
from RFC patch v3 are:
- Enable stream buffering where possible.
- Pass the connection directly, not indirected via disown method.
- "invoke/connect" -> "connect" in commit message.
- Don't try to send disconnect command after connecting.
This series is based on same version as appiled previous version is.
Ilari Liusvaara (8):
Add remote helper debug mode
Support mandatory capabilities
Pass unknown protocols to external protocol handlers
Refactor git transport options parsing
Support taking over transports
Support remote helpers implementing smart transports
Support remote archive from external protocol helpers
Remove special casing of http, https and ftp
.gitignore | 4 +
Documentation/git-remote-helpers.txt | 30 ++++-
Makefile | 24 +++-
builtin-archive.c | 17 ++-
transport-helper.c | 291 ++++++++++++++++++++++++++++++----
transport.c | 228 +++++++++++++++++++++------
transport.h | 22 +++
7 files changed, 523 insertions(+), 93 deletions(-)
^ permalink raw reply
* Re: [PATCH 2/2] t7508-status: test all modes with color
From: Jakub Narebski @ 2009-12-08 11:10 UTC (permalink / raw)
To: git
In-Reply-To: <39211ecec866882503d1188d359e1183341faeb1.1260266027.git.git@drmicha.warpmail.net>
Michael J Gruber wrote:
> +decrypt_color () {
> + sed \
> + -e 's/.\[1m/<WHITE>/g' \
> + -e 's/.\[31m/<RED>/g' \
> + -e 's/.\[32m/<GREEN>/g' \
> + -e 's/.\[34m/<BLUE>/g' \
> + -e 's/.\[m/<RESET>/g'
> +}
Shouldn't this be better in test-lib.sh, or some common lib
(lib-color.sh or color-lib.sh; we are unfortunately a bit inconsistent
in naming here)?
--
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
^ permalink raw reply
* Re: What's cooking in git.git (Dec 2009, #03; Tue, 08)
From: Nguyen Thai Ngoc Duy @ 2009-12-08 10:20 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vmy1tg6ll.fsf@alter.siamese.dyndns.org>
On Tue, Dec 8, 2009 at 4:25 PM, Junio C Hamano > * nd/sparse
(2009-11-25) 20 commits.
> (merged to 'next' on 2009-11-25 at 71380f5)
> + tests: rename duplicate t1009
> (merged to 'next' on 2009-11-23 at f712a41)
> + sparse checkout: inhibit empty worktree
> + Add tests for sparse checkout
> + read-tree: add --no-sparse-checkout to disable sparse checkout support
> + unpack-trees(): ignore worktree check outside checkout area
> + unpack_trees(): apply $GIT_DIR/info/sparse-checkout to the final index
> + unpack-trees(): "enable" sparse checkout and load $GIT_DIR/info/sparse-checkout
> + unpack-trees.c: generalize verify_* functions
> + unpack-trees(): add CE_WT_REMOVE to remove on worktree alone
> + Introduce "sparse checkout"
> + dir.c: export excluded_1() and add_excludes_from_file_1()
> + excluded_1(): support exclude files in index
> + unpack-trees(): carry skip-worktree bit over in merged_entry()
> + Read .gitignore from index if it is skip-worktree
> + Avoid writing to buffer in add_excludes_from_file_1()
> + Teach Git to respect skip-worktree bit (writing part)
> + Teach Git to respect skip-worktree bit (reading part)
> + Introduce "skip-worktree" bit in index, teach Git to get/set this bit
> + Add test-index-version
> + update-index: refactor mark_valid() in preparation for new options
>
> There were some test glitches reported and at least one test seems to
> be broken in the sense that it is not testing what it is trying to.
> Fix-up expected.
Indeed. I'm working on it. Hopefully I'll have something in the next few days.
--
Duy
^ permalink raw reply
* [PATCH 1/2] t7508-status: status --porcelain ignores relative paths setting
From: Michael J Gruber @ 2009-12-08 10:12 UTC (permalink / raw)
To: git; +Cc: Jeff King, Junio C Hamano
In-Reply-To: <cover.1260266027.git.git@drmicha.warpmail.net>
Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>
---
t/t7508-status.sh | 18 ++++++++++++++++++
1 files changed, 18 insertions(+), 0 deletions(-)
diff --git a/t/t7508-status.sh b/t/t7508-status.sh
index 99a74bd..8e7727e 100755
--- a/t/t7508-status.sh
+++ b/t/t7508-status.sh
@@ -298,6 +298,24 @@ test_expect_success 'status -s with relative paths' '
'
cat > expect << \EOF
+ M dir1/modified
+A dir2/added
+?? dir1/untracked
+?? dir2/modified
+?? dir2/untracked
+?? expect
+?? output
+?? untracked
+EOF
+
+test_expect_success 'status --porcelain ignores relative paths setting' '
+
+ (cd dir1 && git status --porcelain) > output &&
+ test_cmp expect output
+
+'
+
+cat > expect << \EOF
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
--
1.6.6.rc1.292.gd8fe
^ permalink raw reply related
* [PATCH 2/2] t7508-status: test all modes with color
From: Michael J Gruber @ 2009-12-08 10:12 UTC (permalink / raw)
To: git; +Cc: Jeff King, Junio C Hamano
In-Reply-To: <cover.1260266027.git.git@drmicha.warpmail.net>
Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>
---
t/t7508-status.sh | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 119 insertions(+), 0 deletions(-)
diff --git a/t/t7508-status.sh b/t/t7508-status.sh
index 8e7727e..50554a0 100755
--- a/t/t7508-status.sh
+++ b/t/t7508-status.sh
@@ -31,6 +31,15 @@ test_expect_success 'setup' '
git add dir2/added
'
+decrypt_color () {
+ sed \
+ -e 's/.\[1m/<WHITE>/g' \
+ -e 's/.\[31m/<RED>/g' \
+ -e 's/.\[32m/<GREEN>/g' \
+ -e 's/.\[34m/<BLUE>/g' \
+ -e 's/.\[m/<RESET>/g'
+}
+
test_expect_success 'status (1)' '
grep "use \"git rm --cached <file>\.\.\.\" to unstage" output
@@ -315,6 +324,115 @@ test_expect_success 'status --porcelain ignores relative paths setting' '
'
+test_expect_success 'setup unique colors' '
+
+ git config status.color.untracked blue
+
+'
+
+cat > expect << \EOF
+# On branch master
+# Changes to be committed:
+# (use "git reset HEAD <file>..." to unstage)
+#
+# <GREEN>new file: dir2/added<RESET>
+#
+# Changed but not updated:
+# (use "git add <file>..." to update what will be committed)
+# (use "git checkout -- <file>..." to discard changes in working directory)
+#
+# <RED>modified: dir1/modified<RESET>
+#
+# Untracked files:
+# (use "git add <file>..." to include in what will be committed)
+#
+# <BLUE>dir1/untracked<RESET>
+# <BLUE>dir2/modified<RESET>
+# <BLUE>dir2/untracked<RESET>
+# <BLUE>expect<RESET>
+# <BLUE>output<RESET>
+# <BLUE>untracked<RESET>
+EOF
+
+test_expect_success 'status with color.ui' '
+
+ git config color.ui always &&
+ git status | decrypt_color > output &&
+ test_cmp expect output
+
+'
+
+test_expect_success 'status with color.status' '
+
+ git config --unset color.ui &&
+ git config color.status always &&
+ git status | decrypt_color > output &&
+ test_cmp expect output
+
+'
+
+cat > expect << \EOF
+ <RED>M<RESET> dir1/modified
+<GREEN>A<RESET> dir2/added
+<BLUE>??<RESET> dir1/untracked
+<BLUE>??<RESET> dir2/modified
+<BLUE>??<RESET> dir2/untracked
+<BLUE>??<RESET> expect
+<BLUE>??<RESET> output
+<BLUE>??<RESET> untracked
+EOF
+
+test_expect_success 'status -s with color.ui' '
+
+ git config --unset color.status &&
+ git config color.ui always &&
+ git status -s | decrypt_color > output &&
+ test_cmp expect output
+
+'
+
+test_expect_success 'status -s with color.status' '
+
+ git config --unset color.ui &&
+ git config color.status always &&
+ git status -s | decrypt_color > output &&
+ test_cmp expect output
+
+'
+
+cat > expect << \EOF
+ M dir1/modified
+A dir2/added
+?? dir1/untracked
+?? dir2/modified
+?? dir2/untracked
+?? expect
+?? output
+?? untracked
+EOF
+
+test_expect_success 'status --porcelain ignores color.ui' '
+
+ git config --unset color.status &&
+ git config color.ui always &&
+ git status --porcelain | decrypt_color > output &&
+ test_cmp expect output
+
+'
+
+test_expect_success 'status --porcelain ignores color.status' '
+
+ git config --unset color.ui &&
+ git config color.status always &&
+ git status --porcelain | decrypt_color > output &&
+ test_cmp expect output
+
+'
+
+# recover unconditionally from color tests
+git config --unset color.status
+git config --unset color.ui
+
cat > expect << \EOF
# On branch master
# Changes to be committed:
@@ -339,6 +457,7 @@ cat > expect << \EOF
# untracked
EOF
+
test_expect_success 'status without relative paths' '
git config status.relativePaths false
--
1.6.6.rc1.292.gd8fe
^ permalink raw reply related
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