* Re: is gitosis secure?
From: Sam Vilain @ 2008-12-09 9:04 UTC (permalink / raw)
To: Thomas Koch; +Cc: Git Mailing List, dabe
In-Reply-To: <200812090956.48613.thomas@koch.ro>
On Tue, 2008-12-09 at 09:56 +0100, Thomas Koch wrote:
> Sorry for the shameless subject, but I presented gitosis yesterday to
> our sysadmin and he wasn't much delighted to learn, that write access to
> repositories hosted with gitosis would need SSH access.
>
> So could you help me out in this discussion, whether to use or not to
> use gitosis?
> Our admin would prefer to not open SSH at all outside our LAN, but
> developers would need to have write access also outside the office.
Restricted unix shells are a technology which has been proven secure for
decades now. If you use git-shell, you are keeping the secure part of
SSH - the authentication and encryption - and restricting the SSH access
part to the bare minimum required for useful access to the required
services.
ie ... it all comes down to the shell you give those 'login' users as to
what they can do.
Sam.
^ permalink raw reply
* Re: How to clone git repository with git-svn meta-data included?
From: Sam Vilain @ 2008-12-09 9:08 UTC (permalink / raw)
To: Grzegorz Kossakowski; +Cc: Peter Harris, Michael J Gruber, git
In-Reply-To: <493D6AE9.6020504@tuffmail.com>
On Mon, 2008-12-08 at 19:43 +0100, Grzegorz Kossakowski wrote:
> > Yes. The rfoo = sha1hash part is git-svn rebuilding its index.
> > "Current branch master is up to date" is git-svn calling "git rebase
> > <svn-branch>", and git saying that there is nothing to do, since there
> > have been no svn commits to that branch since the last time you ran
> > git svn rebase (or since you cloned the git mirror, or since the last
> > time the git mirror pulled from svn).
>
> Thanks for confirmation and explanation.
>
> The remaining question is who should address this issue with non-existing trunk ref? Should I ask
> Jukka, who maintains svn mirrors, to put instruction into his scripts that will add trunk reference?
It's up to the git-svn user to make sure that they prepare the refs to
be what git-svn expects. This is something probably requiring more
documentation and/or git-svn features to be easier.
> Would it be the best practice?
Well, obscure stuff should never really be best practice. The best practice
is to have a single git repository that is where the svn -> git migration
happens. And git-svn could perhaps auto-init based on information in the
commit log or something. Best practice is to enhance the tool to work the
way it Should(tm) :)
Sam
^ permalink raw reply
* Re: Problems Cloning an SVN repo.
From: Tim Visher @ 2008-12-09 19:41 UTC (permalink / raw)
To: Peter Harris; +Cc: git
In-Reply-To: <eaa105840812091009k292ced25vcd638808c913b76@mail.gmail.com>
> Did you install the subversion-perl cygwin package?
That was it. Thanks everyone!
--
In Christ,
Timmy V.
http://burningones.com/
http://five.sentenc.es/ - Spend less time on e-mail
^ permalink raw reply
* Re: [PATCH] make sure packs to be replaced are closed beforehand
From: Alex Riesen @ 2008-12-09 19:33 UTC (permalink / raw)
To: Nicolas Pitre; +Cc: Johannes Sixt, Junio C Hamano, Git Mailing List
In-Reply-To: <alpine.LFD.2.00.0812091414030.14328@xanadu.home>
Nicolas Pitre, Tue, Dec 09, 2008 20:26:52 +0100:
> Especially on Windows where an opened file cannot be replaced, make
> sure pack-objects always close packs it is about to replace. Even on
> non Windows systems, this could save potential bad results if ever
> objects were to be read from the new pack file using offset from the old
> index.
>
> This should fix t5303 on Windows.
>
> Signed-off-by: Nicolas Pitre <nico@cam.org>
> ---
...
> OK, here it is at last. Please confirm it works on Windows before Junio
> merges it.
>
Will do in about 16 hours.
^ permalink raw reply
* [PATCH] make sure packs to be replaced are closed beforehand
From: Nicolas Pitre @ 2008-12-09 19:26 UTC (permalink / raw)
To: Alex Riesen; +Cc: Johannes Sixt, Junio C Hamano, Git Mailing List
In-Reply-To: <alpine.LFD.2.00.0811260931030.14328@xanadu.home>
Especially on Windows where an opened file cannot be replaced, make
sure pack-objects always close packs it is about to replace. Even on
non Windows systems, this could save potential bad results if ever
objects were to be read from the new pack file using offset from the old
index.
This should fix t5303 on Windows.
Signed-off-by: Nicolas Pitre <nico@cam.org>
---
On Wed, 26 Nov 2008, Nicolas Pitre wrote:
> On Wed, 26 Nov 2008, Alex Riesen wrote:
> > 2008/11/19 Nicolas Pitre <nico@cam.org>:
> > > On Wed, 19 Nov 2008, Johannes Sixt wrote:
> > >> Oh, the patch only works around the failure in the test case. In a real
> > >> repository there is usually no problem because the destination pack file
> > >> does not exist.
> > >>
> > >> The unusual case is where you do this:
> > >>
> > >> $ git rev-list -10 HEAD | git pack-objects foobar
> > >>
> > >> twice in a row: In this case the second invocation fails on Windows
> > >> because the destination pack file already exists *and* is open. But not
> > >> even git-repack does this even if it is called twice. OTOH, the test case
> > >> *does* exactly this.
> > >
> > > OK.... Well, despite my earlier assertion, I think the above should be a
> > > valid operation.
> > >
> > > I'm looking at it now. I'm therefore revoking my earlier ACK as well
> > > (better keep that test case alive).
> > >
> >
> > Any news here?
>
> Yes: my hard disk crashed a couple hours after I mentioned this, so most
> of my time has been spent on recovery since then. I'll come back to it
> eventually.
OK, here it is at last. Please confirm it works on Windows before Junio
merges it.
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index 67eefa2..cedef52 100644
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
@@ -535,6 +535,7 @@ static void write_pack_file(void)
snprintf(tmpname, sizeof(tmpname), "%s-%s.pack",
base_name, sha1_to_hex(sha1));
+ free_pack_by_name(tmpname);
if (adjust_perm(pack_tmp_name, mode))
die("unable to make temporary pack file readable: %s",
strerror(errno));
diff --git a/cache.h b/cache.h
index f15b3fc..231c06d 100644
--- a/cache.h
+++ b/cache.h
@@ -820,6 +820,7 @@ extern int open_pack_index(struct packed_git *);
extern unsigned char* use_pack(struct packed_git *, struct pack_window **, off_t, unsigned int *);
extern void close_pack_windows(struct packed_git *);
extern void unuse_pack(struct pack_window **);
+extern void free_pack_by_name(const char *);
extern struct packed_git *add_packed_git(const char *, int, int);
extern const unsigned char *nth_packed_object_sha1(struct packed_git *, uint32_t);
extern off_t nth_packed_object_offset(const struct packed_git *, uint32_t);
diff --git a/sha1_file.c b/sha1_file.c
index 6c0e251..0e021c5 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -673,6 +673,37 @@ void unuse_pack(struct pack_window **w_cursor)
}
/*
+ * This is used by git-repack in case a newly created pack happens to
+ * contain the same set of objects as an existing one. In that case
+ * the resulting file might be different even if its name would be the
+ * same. It is best to close any reference to the old pack before it is
+ * replaced on disk. Of course no index pointers nor windows for given pack
+ * must subsist at this point. If ever objects from this pack are requested
+ * again, the new version of the pack will be reinitialized through
+ * reprepare_packed_git().
+ */
+void free_pack_by_name(const char *pack_name)
+{
+ struct packed_git *p, **pp = &packed_git;
+
+ while (*pp) {
+ p = *pp;
+ if (strcmp(pack_name, p->pack_name) == 0) {
+ close_pack_windows(p);
+ if (p->pack_fd != -1)
+ close(p->pack_fd);
+ if (p->index_data)
+ munmap((void *)p->index_data, p->index_size);
+ free(p->bad_object_sha1);
+ *pp = p->next;
+ free(p);
+ return;
+ }
+ pp = &p->next;
+ }
+}
+
+/*
* Do not call this directly as this leaks p->pack_fd on error return;
* call open_packed_git() instead.
*/
^ permalink raw reply related
* Re: is gitosis secure?
From: Garry Dolley @ 2008-12-09 19:18 UTC (permalink / raw)
To: Thomas Koch; +Cc: Git Mailing List, dabe
In-Reply-To: <200812090956.48613.thomas@koch.ro>
On Tue, Dec 09, 2008 at 09:56:48AM +0100, Thomas Koch wrote:
> Sorry for the shameless subject, but I presented gitosis yesterday to
> our sysadmin and he wasn't much delighted to learn, that write access to
> repositories hosted with gitosis would need SSH access.
>
> So could you help me out in this discussion, whether to use or not to
> use gitosis?
> Our admin would prefer to not open SSH at all outside our LAN, but
> developers would need to have write access also outside the office.
If your admin doesn't want to open SSH to the outside, then the
people who need it would need to VPN into your LAN first. That's
how I do it on networks that don't allow any traffic from the
outside.
But like someone else ask, what alternative *would* your admin
prefer? I'd rather use SSH than a yet-to-be-proven-secure
alternative app.
--
Garry Dolley
ARP Networks, Inc. http://www.arpnetworks.com
Data center, VPS, and IP transit solutions (818) 206-0181
Member Los Angeles County REACT, Unit 336 WQGK336
Blog http://scie.nti.st
^ permalink raw reply
* Re: git fsck segmentation fault
From: Nicolas Pitre @ 2008-12-09 19:09 UTC (permalink / raw)
To: Simon Hausmann; +Cc: Martin Koegler, Git Mailing List
In-Reply-To: <200811280919.10685.simon@lst.de>
Has this been looked at? Martin?
On Fri, 28 Nov 2008, Simon Hausmann wrote:
> On Thursday 27 November 2008 Nicolas Pitre, wrote:
> > On Thu, 27 Nov 2008, Simon Hausmann wrote:
> > > On Thursday 27 November 2008 20:10:20 Simon Hausmann wrote:
> > > > On Thursday 27 November 2008 18:47:41 Nicolas Pitre wrote:
> > > > > On Thu, 27 Nov 2008, Simon Hausmann wrote:
> > > > > > Hi,
> > > > > >
> > > > > > when running git fsck --full -v (version 1.6.0.4.26.g7c30c) on a
> > > > > > medium sized
> > > > >
> > > > > That version doesn't exist in the git repo.
> > > >
> > > > Ah, oops, it was a merge commit, corresponding to maint as of 5aa3bd.
> > > >
> > > > > > (930M) repository I get a segfault.
> > > > > >
> > > > > > The backtrace indicates an infinite recursion. Here's the output
> > > > > > from the last few lines:
> > > > >
> > > > > [...]
> > > > >
> > > > > Could you try with latest master branch please? It is more robust
> > > > > against some kind of pack corruptions that could send the code into
> > > > > infinite loops.
> > > >
> > > > Same problem with git version 1.6.0.4.790.gaa14a
> > >
> > > Forgot to paste the changed line numbers of the recursion:
> >
> > [...]
> >
> > Well... Your initial backtrace showed recursion in unpack_entry() which
> > was rather odd in the first place. Your latest backtrace shows a loop
> > in make_object() which has nothing to do what so ever with
> > unpack_entry(). So the backtrace might not be really useful.
> >
> > I suspect you'll have to bisect git to find the issue, given that some
> > old version can be found to be good. For example, does it work with
> > v1.5.2.5?
>
> Ah yes, v1.5.2.5 works! (phew, and it verified that the repo is fine)
>
> Ok, I bisected and "git bisect run" identified the following commit as first bad
> commit:
>
> commit 271b8d25b25e49b367087440e093e755e5f35aa9
> Author: Martin Koegler <mkoegler@auto.tuwien.ac.at>
> Date: Mon Feb 25 22:46:05 2008 +0100
>
> builtin-fsck: move away from object-refs to fsck_walk
>
>
>
>
> Simon
>
^ permalink raw reply
* Re: Problems Cloning an SVN repo.
From: Deskin Miller @ 2008-12-09 18:12 UTC (permalink / raw)
To: Tim Visher; +Cc: git
In-Reply-To: <c115fd3c0812090954n6e5e527anadf04936e1ca01f@mail.gmail.com>
On Tue, Dec 09, 2008 at 12:54:20PM -0500, Tim Visher wrote:
> Can't locate SVN/Core.pm in @INC (@INC contains:
This is perl's way of saying "you don't have the SVN perl bindings in
some place I can find them". I've not used git-svn under cygwin and
lack a windows computer to test, but on debian the SVN perl bindings are
in packages called libsvn-perl or libsvn-core-perl; I'd look for
similarly-named packages in cygwin's installer, or alternately packages
related to SVN. If you're sure that the bindings are already installed,
you can fiddle with perl's module search path to detect them in an
unusual location: look at the -I flag to perl.
If that doesn't work, you can try building svn from source under cygwin,
and installing the perl bindings that way.
Hope that helps,
Deskin Miller
^ permalink raw reply
* Re: Problems Cloning an SVN repo.
From: Peter Harris @ 2008-12-09 18:09 UTC (permalink / raw)
To: Tim Visher; +Cc: git
In-Reply-To: <c115fd3c0812090954n6e5e527anadf04936e1ca01f@mail.gmail.com>
On Tue, Dec 9, 2008 at 12:54 PM, Tim Visher wrote:
> Hello everyone,
>
> I'm trying to use `git svn clone` to begin to work with a project
> stored in subversion through git for the work I do on the project
> locally. I installed git through cygwin and I'm getting the following
> error when executing the command.
>
> Can't locate SVN/Core.pm in @INC (@INC contains:
> /usr/lib/perl5/site_perl/5.10 /usr/lib/perl5/5.10/i686-cygwin
> /usr/lib/perl5/5.10 /usr/lib/perl5/site_perl/5.10/i686-cygwin
> /usr/lib/perl5/vendor_perl/5.10/i686-cygwin
> /usr/lib/perl5/vendor_perl/5.10 /usr/lib/perl5/site_perl/5.8
> /usr/lib/perl5/vendor_perl/5.8 .) at /usr/sbin/git-core//git-svn line
> 29.
>
> Any help?
Did you install the subversion-perl cygwin package?
Peter Harris
^ permalink raw reply
* Problems Cloning an SVN repo.
From: Tim Visher @ 2008-12-09 17:54 UTC (permalink / raw)
To: git
Hello everyone,
I'm trying to use `git svn clone` to begin to work with a project
stored in subversion through git for the work I do on the project
locally. I installed git through cygwin and I'm getting the following
error when executing the command.
Can't locate SVN/Core.pm in @INC (@INC contains:
/usr/lib/perl5/site_perl/5.10 /usr/lib/perl5/5.10/i686-cygwin
/usr/lib/perl5/5.10 /usr/lib/perl5/site_perl/5.10/i686-cygwin
/usr/lib/perl5/vendor_perl/5.10/i686-cygwin
/usr/lib/perl5/vendor_perl/5.10 /usr/lib/perl5/site_perl/5.8
/usr/lib/perl5/vendor_perl/5.8 .) at /usr/sbin/git-core//git-svn line
29.
Any help?
--
In Christ,
Timmy V.
http://burningones.com/
http://five.sentenc.es/ - Spend less time on e-mail
^ permalink raw reply
* Re: git-bpush: Pushing to a bundle
From: Junio C Hamano @ 2008-12-09 17:32 UTC (permalink / raw)
To: Santi Béjar; +Cc: Johannes Schindelin, git list
In-Reply-To: <adf1fd3d0812090221t2264a4f9i87b5e23be897ee84@mail.gmail.com>
"Santi Béjar" <santi@agolina.net> writes:
> I do not find convenient strictly incremental bundles, because then
> you (or the other people) needs to fetch every single bundle. What I
> do is add new objects until the bundle is too big and then create a
> bundle with a new base. This way you don't have to worry if the other
> person has applied the last bundle or not.
You both have good points. I sort of tend to side with your argument from
convenience point of view, if only because that resembles the way how
people traditionally arrange incremental backups "a full dump on Sunday
night, and every day incremental relative to the last full dump". Dscho's
suggestion is akin to "a full dump on Sunday night, and every day
incremental relative to the previous day". Both form obviously can
recreate the same contents, but often "incremental since the last full
synchronization point", even though it may make bigger dumps, is easier to
handle for humans.
>> IOW if you already have a bundle,
>> you want to create a new bundle that contains everything that is new, _in
>> addition_ to the existing bundle.
>
>>> while [ $# != 0 ] ; do
>>
>> Heh, I did not realize just how _used_ I got to the conventions in Git's
>> shell programming, until I thought "Should this not use 'test' instead
>> of brackets?"
Now I see you are improving ;-)
>>> while [ $# != 0 ] ; do
>>> refs="$refs$LF$1" && shift
>>> done
>>
>> That is equivalent to refs="$*", no?
>
> Almost, IFS is set to line-feed so I needed to put $LF instead of spaces.
If $IFS is set to LF, "$*" will be $1, $2, $3 concatenated with LF in
between. The first character in $IFS is used for that purpose..
^ permalink raw reply
* Re: Getting submodules to follow symlinks?
From: Edward Z. Yang @ 2008-12-09 17:29 UTC (permalink / raw)
To: git
In-Reply-To: <57518fd10812090455wd109843mfece11eae9e4f593@mail.gmail.com>
Jonathan del Strother wrote:
> My git repository contains a symlink to another repository. I'd like
> to make that second repository a submodule of the first, in such a way
> that when someone else clones the repository, there's no trace of the
> original symlink.
Yeah. If you register the submodule and then commit, the first
repository would contain the submodule information, and anyone who loads
submodules in another clone will not see the symlink.
Cheers,
Edward
^ permalink raw reply
* [PATCH] Fix typos in documentation
From: Alexander Potashev @ 2008-12-09 17:26 UTC (permalink / raw)
To: git; +Cc: gitster, Alexander Potashev
Signed-off-by: Alexander Potashev <aspotashev@gmail.com>
---
Documentation/git-send-email.txt | 2 +-
Documentation/technical/racy-git.txt | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
index acf8bf4..1278866 100644
--- a/Documentation/git-send-email.txt
+++ b/Documentation/git-send-email.txt
@@ -46,7 +46,7 @@ The --cc option must be repeated for each user you want on the cc list.
Use $GIT_EDITOR, core.editor, $VISUAL, or $EDITOR to edit an
introductory message for the patch series.
+
-When compose is in used, git send-email gets less interactive will use the
+When '--compose' is used, git send-email gets less interactive will use the
values of the headers you set there. If the body of the email (what you type
after the headers and a blank line) only contains blank (or GIT: prefixed)
lines, the summary won't be sent, but git-send-email will still use the
diff --git a/Documentation/technical/racy-git.txt b/Documentation/technical/racy-git.txt
index 6bdf034..48bb97f 100644
--- a/Documentation/technical/racy-git.txt
+++ b/Documentation/technical/racy-git.txt
@@ -135,7 +135,7 @@ them, and give the same timestamp to the index file:
This will make all index entries racily clean. The linux-2.6
project, for example, there are over 20,000 files in the working
-tree. On my Athron 64X2 3800+, after the above:
+tree. On my Athlon 64 X2 3800+, after the above:
$ /usr/bin/time git diff-files
1.68user 0.54system 0:02.22elapsed 100%CPU (0avgtext+0avgdata 0maxresident)k
--
1.6.0.4
^ permalink raw reply related
* Re: Forcing --no-ff on pull
From: Stephen Haberman @ 2008-12-09 16:39 UTC (permalink / raw)
To: R. Tyler Ballance; +Cc: git
In-Reply-To: <1228817565.18611.54.camel@starfruit.local>
> > $ git config branch.stable.mergeoptions "--no-ff"
>
> I recall stumbling across this a while ago looking at the git-config(1)
> man page, but this isn't /quite/ what we need.
>
> I'm talking about forcing for *every* pull, it's a safe assumption to
> make that we want a merge commit every time somebody fast-forwards a
> branch.
>
> The only way I could think to make use of branch.<name>.mergeoptions
> would be to automagically set it up in a "pre-merge" hook, but alas
> post-merge exists but not pre-merge.
I had done something like this with a post-checkout hook. After checking
out any branch, the hook sets various branch.<name>.options.
Also, I wrote a hook to enforce "only no-ff commits can move stable" and
other fun stuff. It's out on github, in a semi-documented/unannounced
project with the email/trac/etc. hooks we put in place:
http://github.com/stephenh/gc/tree/master/server/update-stable
- Stephen
^ permalink raw reply
* Re: [PATCH/RFC] Allow writing loose objects that are corrupted in a pack file
From: Shawn O. Pearce @ 2008-12-09 16:24 UTC (permalink / raw)
To: Jan Krüger; +Cc: Git ML, tyler
In-Reply-To: <20081209093627.77039a1f@perceptron>
Jan Krüger <jk@jk.gs> wrote:
> For fixing a corrupted repository by using backup copies of individual
> files, allow write_sha1_file() to write loose files even if the object
> already exists in a pack file, but only if the existing entry is marked
> as corrupted.
Huh. So I'm digging around sha1_file.c and I'm not yet sure why
your patch makes a difference.
has_sha1_file() calls find_pack_entry() to determine which pack has
the object, and at what offset (if found). It doesn't care about
the offset, but it does care about the successful match.
find_pack_entry() already considers the bad_object_sha1 for each
pack, before it even tries the binary search within the index.
So if the entry was known to be bad has_sha1_file() will return 0,
unless the object is loose.
Where this breaks down is if the object is being created,
its very likely we didn't attempt to read it in this process.
The bad_object_sha1 table is transient and populated only when
unpacking an object entry fails. So for example during a merge
if a tree was stored in a pack and is corrupt and the merge
result produces that same tree object we won't write it out with
write_sha1_file() because it exists in a pack, but since we never
read it we also don't know the pack entry is corrupt.
Its horribly inefficient to read every object before we write it
back out. The best thing to do when faced with corruption is to
stop and repack, overlaying the object database from a known good
copy of the repository so pack-objects can use the good copy when
a corrupt object is identified.
So I agree with you that changing this in write_sha1_file() is a
bad idea for the normal good cases, but I also don't see how this
patch changes anything at all... the code path you introduced is
already implemented.
> diff --git a/sha1_file.c b/sha1_file.c
> index 6c0e251..17085cc 100644
> --- a/sha1_file.c
> +++ b/sha1_file.c
> @@ -2373,14 +2373,17 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha
> char hdr[32];
> int hdrlen;
>
> - /* Normally if we have it in the pack then we do not bother writing
> - * it out into .git/objects/??/?{38} file.
> - */
> write_sha1_file_prepare(buf, len, type, sha1, hdr, &hdrlen);
> if (returnsha1)
> hashcpy(returnsha1, sha1);
> - if (has_sha1_file(sha1))
> - return 0;
> + /* Normally if we have it in the pack then we do not bother writing
> + * it out into .git/objects/??/?{38} file. We do, though, if there
> + * is no chance that we have an uncorrupted version of the object.
> + */
> + if (has_sha1_file(sha1)) {
> + if (has_loose_object(sha1) || !has_packed_and_bad(sha1))
> + return 0;
> + }
> return write_loose_object(sha1, hdr, hdrlen, buf, len, 0);
> }
--
Shawn.
^ permalink raw reply
* Re: get upstream branch
From: Santi Béjar @ 2008-12-09 15:51 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Jeff King, Jeff Whiteside, Git Mailing List
In-Reply-To: <7v8wqp6e89.fsf@gitster.siamese.dyndns.org>
2008/12/9 Junio C Hamano <gitster@pobox.com>:
> Jeff King <peff@peff.net> writes:
>
>> In one of my scripts I do something like this (actually this is not
>> straight from my script, as the operation there is "find all pairs of
>> local/remote branches" and this is "find the current upstream"):
>>
>> ref=`git symbolic-ref HEAD`
>> head=${ref#refs/heads/}
>> remote=`git config branch.$head.remote`
>> branch=`git config branch.$head.merge`
>> echo refs/remote/$remote/${branch#refs/heads/}
>>
>> And obviously this is missing error checking for the detached HEAD
>> (symbolic-ref should fail) and no tracking branch ($remote and/or $branch
>> will be empty) cases.
>
> Yeah, add any nonstandard layout to that set of things that are missing,
> but in practice it should not matter.
In "git pull --rebase" this is used to know the hash of the tracking branch:
. git-parse-remote &&
origin="$1"
test -z "$origin" && origin=$(get_default_remote)
reflist="$(get_remote_refs_for_fetch "$@" 2>/dev/null |
sed "s|refs/heads/\(.*\):|\1|")" &&
oldremoteref="$(git rev-parse -q --verify \
"refs/remotes/$origin/$reflist")"
Santi
^ permalink raw reply
* [PATCH] git-p4: Fix regression in p4Where method.
From: Tor Arvid Lund @ 2008-12-09 15:41 UTC (permalink / raw)
To: Junio C Hamano, Simon Hausmann; +Cc: git, Tor Arvid Lund
Unfortunately, I introduced a bug in commit 7f705dc36 (git-p4: Fix bug in
p4Where method). This happens because sometimes the result from
"p4 where <somepath>" doesn't contain a "depotFile" key, but instead a
"data" key that needs further parsing. This commit should ensure that both
of these cases are checked.
Signed-off-by: Tor Arvid Lund <torarvid@gmail.com>
---
contrib/fast-import/git-p4 | 13 ++++++++++---
1 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4
index ee504e9..a85a7b2 100755
--- a/contrib/fast-import/git-p4
+++ b/contrib/fast-import/git-p4
@@ -249,9 +249,16 @@ def p4Where(depotPath):
outputList = p4CmdList("where %s" % depotPath)
output = None
for entry in outputList:
- if entry["depotFile"] == depotPath:
- output = entry
- break
+ if "depotFile" in entry:
+ if entry["depotFile"] == depotPath:
+ output = entry
+ break
+ elif "data" in entry:
+ data = entry.get("data")
+ space = data.find(" ")
+ if data[:space] == depotPath:
+ output = entry
+ break
if output == None:
return ""
if output["code"] == "error":
--
1.6.0.2.1172.ga5ed0
^ permalink raw reply related
* [PATCH] git-gui: Updated Swedish translation (515t0f0u).
From: Peter Krefting @ 2008-12-09 15:25 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: Git Mailing List
In-Reply-To: <20081208163628.GG31551@spearce.org>
[-- Attachment #1: Type: TEXT/PLAIN, Size: 210 bytes --]
Shawn O. Pearce:
> Since my last request to update translations we also picked up one
> new message string:
Patch to the Swedish translation is attached gzipped.
--
\\// Peter - http://www.softwolves.pp.se/
[-- Attachment #2: Type: APPLICATION/OCTET-STREAM, Size: 4985 bytes --]
^ permalink raw reply
* Re: get upstream branch
From: Peter Harris @ 2008-12-09 15:25 UTC (permalink / raw)
To: Jeff Whiteside; +Cc: Git Mailing List
In-Reply-To: <3ab397d0812082052j6a45d05dr1c863aa260826f4@mail.gmail.com>
On Mon, Dec 8, 2008 at 11:52 PM, Jeff Whiteside wrote:
>
> Does anyone know how to programmatically get the upstream/parent
> branch of a branch? I'm trying to write a gui, but looking at gitk's
> tcl code isn't helping me much.
Would C++ code be a better help?
qgit is somewhat similar to gitk:
http://digilander.libero.it/mcostalba/
git://git.kernel.org/pub/scm/qgit/qgit.git
git://git.kernel.org/pub/scm/qgit/qgit4.git
Peter Harris
^ permalink raw reply
* Re: git-bpush: Pushing to a bundle
From: Santi Béjar @ 2008-12-09 14:58 UTC (permalink / raw)
To: Johannes Sixt; +Cc: Johannes Schindelin, git list
In-Reply-To: <493E545B.6010609@viscovery.net>
[-- Attachment #1: Type: text/plain, Size: 5667 bytes --]
2008/12/9 Johannes Sixt <j.sixt@viscovery.net>:
> Santi Béjar schrieb:
>> 2008/12/9 Johannes Schindelin <Johannes.Schindelin@gmx.de>:
>>> On Tue, 9 Dec 2008, Santi Béjar wrote:
>>>> while [ $# != 0 ] ; do
>>>> refs="$refs$LF$1" && shift
>>>> done
>>> That is equivalent to refs="$*", no?
>>
>> Almost, IFS is set to line-feed so I needed to put $LF instead of spaces.
>
> But "$*" inserts the first character of IFS (not necessarily spaces), and
> since your IFS *is* $LF, "$*" should do what you want.
>
Oh, you are right.
> Anyway, I found reading your shell script quite hard, because of excessive
> use of brackets and single line && chains (which lack proper error
> handling, BTW).
I've changed the script to follow the Git's conventions (at least I've
tried), a few more error handling and some simplification. BTW, what
do you find hard with single line && chains?
I do not sent a diff because it is almost as big as the script itself.
#!/bin/sh
OPTIONS_KEEPDASHDASH=
OPTIONS_SPEC="\
git bpush [options] [<remote> [<refs>...]]
--
f,force force updates
full create a full bundle
v be verbose
"
SUBDIRECTORY_OK=Yes
. git-sh-setup
. git-parse-remote
cd_to_toplevel
LF='
'
IFS="$LF"
bases=
bbases=
changed=
force=
nonff=
remote=
refs=
while :
do
case "$1" in
-v)
verbose=t ;;
--full)
full=t ;;
-f|--force)
force=t ;;
--)
shift
break ;;
*)
usage ;;
esac
shift
done
test -n "$1" && remote=$1 && shift
refs="$*"
test -z "$remote" && remote=$(get_default_remote)
remoteurl=$(git config remote.${remote}.url)
test -z "$remoteurl" && remoteurl=$remote
test -d "$remoteurl" && die "$remoteurl is a directory"
# Default bases in bundle.base
# Default {refs,base} can be specified in remote.<remote>.{push,bundlebase}
if test "$remote" != "$remoteurl"
then
test -z "$refs" &&
refs=$(git config --get-all remote.${remote}.push)
bases=$(git config --get-all remote.${remote}.bundlebase ||
git config --get-all bundle.base)
else
bases=$(git config --get-all bundle.base)
fi
# git rev-parse --symbolic-full-name resolves symlinks
# Keep at least HEAD
head=
for ref in $refs ; do
test "$ref" = HEAD && head=t && break
done
test -n "$bases" && bases=$(git rev-parse --revs-only $bases | sort -u)
# Full symbolic refs need to be uniq
test -n "$refs" &&
refs=$(git-rev-parse --symbolic-full-name --revs-only $refs | sort -u)
test -n "$head" && refs="HEAD$LF$refs"
if test -e "$remoteurl"
then
blines=$(git bundle verify "$remoteurl" 2>/dev/null) ||
die "Verification of \"$remoteurl\" failed"
# Find the bundle's bases
refs="$refs$LF$(git bundle list-heads $remoteurl | cut -d " " -f 2)"
requires=
for line in $blines
do
case "$requires,$line" in
",The bundle requires"*)
requires=t ;;
t,) ;;
t,*)
bbase=$(echo $line | cut -d " " -f 1)
bbases="$bbases$LF$bbase"
;;
esac
done
bases="$bases$LF$bbases"
elif test -z "$refs" ; then
# Push current branch
refs="HEAD$LF$(git symbolic-ref -q HEAD)"
fi
test -z "$refs" && die "No refs to push"
refs=$(echo "$refs" | sort -u)
for ref in $bases $refs
do
test "$(git cat-file -t $ref^{})" != commit &&
die "$(basename $0): $ref is not a commit"
done
header="To $remoteurl"
test -n "$verbose" && echo "Pushing to $remoteurl" && echo $header && header=
# Find what is/is not a fast-forward, up to date or new
# As "git bundle" does not support refspecs we must push all matching branches
for ref in $refs ; do
text=
bchanged=
case $ref in
refs/tags/*)
bshort=$(echo $ref | sed -e "s|^refs/tags/||")
newtext="new tag";;
refs/heads/*|HEAD)
bshort=$(echo $ref | sed -e "s|^refs/heads/||")
newtext="new branch" ;;
esac
newhash=$(git rev-parse $ref) || die "Ref $ref not valid"
newshort=$(git rev-parse --short $ref)
bheads=
test -e "$remoteurl" && bheads="$(git bundle list-heads $remoteurl)"
for bhead in $bheads
do
bhash=$(echo $bhead | cut -d " " -f 1)
bref=$(echo $bhead | cut -d " " -f 2)
# Find the matching ref in the bundle
test "$bref" != "$ref" && continue
oldshort=$(git rev-parse --short $bhash)
mergebase=
case $ref in
refs/tags/*)
# Only test if it is different
mergebase=$newhash;;
refs/heads/*|HEAD)
mergebase=$(git merge-base $bref $bhash);;
esac
case $newhash,$bhash,$mergebase,$force in
$bhash,$newhash,*)
# No changes
text=" = [up to date] $bshort -> $bshort"
;;
*,*,$bhash,*)
# Fast-forward
bchanged=t
text=" $oldshort..$newshort $bshort -> $bshort"
;;
*,t)
# Forced non fast-forward
bchanged=t
text=" + $oldshort...$newshort $bshort -> $bshort (forced update)"
;;
*)
bchanged=t
nonff=t
text=" ! [rejected] $bshort -> $bshort (non-fast forward)"
esac
break
done
test -z "$text" && text=" * [$newtext] $bshort -> $bshort" && bchanged=t
if test -n "$bchanged" || test -n "$verbose"
then
test -n "$header" && echo $header && header=
echo $text
fi
test -n "$bchanged" && changed=t
done
# Recreate the bundle if --full and the current bundle is not full
test -n "$full" && bases= && test -n "$bbases" && changed=t
test -n "$nonff" && die "error: failed to push some refs to $remoteurl"
test -z "$changed" && die "Everything up-to-date"
test -n "$bases" && bases="--not$LF$bases"
git bundle create $remoteurl $refs $bases ||
die "Cannot create bundle \"$remoteurl\""
test "$remote" != "$remoteurl" && { git fetch -q "$remote" ||
die "Error fetch from bundle \"$remoteurl\"" ; }
exit 0
[-- Attachment #2: git-bpush --]
[-- Type: application/octet-stream, Size: 4493 bytes --]
#!/bin/sh
OPTIONS_KEEPDASHDASH=
OPTIONS_SPEC="\
git bpush [options] [<remote> [<refs>...]]
--
f,force force updates
full create a full bundle
v be verbose
"
SUBDIRECTORY_OK=Yes
. git-sh-setup
. git-parse-remote
cd_to_toplevel
LF='
'
IFS="$LF"
bases=
bbases=
changed=
force=
nonff=
remote=
refs=
while :
do
case "$1" in
-v)
verbose=t ;;
--full)
full=t ;;
-f|--force)
force=t ;;
--)
shift
break ;;
*)
usage ;;
esac
shift
done
test -n "$1" && remote=$1 && shift
refs="$*"
test -z "$remote" && remote=$(get_default_remote)
remoteurl=$(git config remote.${remote}.url)
test -z "$remoteurl" && remoteurl=$remote
test -d "$remoteurl" && die "$remoteurl is a directory"
# Default bases in bundle.base
# Default {refs,base} can be specified in remote.<remote>.{push,bundlebase}
if test "$remote" != "$remoteurl"
then
test -z "$refs" &&
refs=$(git config --get-all remote.${remote}.push)
bases=$(git config --get-all remote.${remote}.bundlebase ||
git config --get-all bundle.base)
else
bases=$(git config --get-all bundle.base)
fi
# git rev-parse --symbolic-full-name resolves symlinks
# Keep at least HEAD
head=
for ref in $refs ; do
test "$ref" = HEAD && head=t && break
done
test -n "$bases" && bases=$(git rev-parse --revs-only $bases | sort -u)
# Full symbolic refs need to be uniq
test -n "$refs" &&
refs=$(git-rev-parse --symbolic-full-name --revs-only $refs | sort -u)
test -n "$head" && refs="HEAD$LF$refs"
if test -e "$remoteurl"
then
blines=$(git bundle verify "$remoteurl" 2>/dev/null) ||
die "Verification of \"$remoteurl\" failed"
# Find the bundle's bases
refs="$refs$LF$(git bundle list-heads $remoteurl | cut -d " " -f 2)"
requires=
for line in $blines
do
case "$requires,$line" in
",The bundle requires"*)
requires=t ;;
t,) ;;
t,*)
bbase=$(echo $line | cut -d " " -f 1)
bbases="$bbases$LF$bbase"
;;
esac
done
bases="$bases$LF$bbases"
elif test -z "$refs" ; then
# Push current branch
refs="HEAD$LF$(git symbolic-ref -q HEAD)"
fi
test -z "$refs" && die "No refs to push"
refs=$(echo "$refs" | sort -u)
for ref in $bases $refs
do
test "$(git cat-file -t $ref^{})" != commit &&
die "$(basename $0): $ref is not a commit"
done
header="To $remoteurl"
test -n "$verbose" && echo "Pushing to $remoteurl" && echo $header && header=
# Find what is/is not a fast-forward, up to date or new
# As "git bundle" does not support refspecs we must push all matching branches
for ref in $refs ; do
text=
bchanged=
case $ref in
refs/tags/*)
bshort=$(echo $ref | sed -e "s|^refs/tags/||")
newtext="new tag";;
refs/heads/*|HEAD)
bshort=$(echo $ref | sed -e "s|^refs/heads/||")
newtext="new branch" ;;
esac
newhash=$(git rev-parse $ref) || die "Ref $ref not valid"
newshort=$(git rev-parse --short $ref)
bheads=
test -e "$remoteurl" && bheads="$(git bundle list-heads $remoteurl)"
for bhead in $bheads
do
bhash=$(echo $bhead | cut -d " " -f 1)
bref=$(echo $bhead | cut -d " " -f 2)
# Find the matching ref in the bundle
test "$bref" != "$ref" && continue
oldshort=$(git rev-parse --short $bhash)
mergebase=
case $ref in
refs/tags/*)
# Only test if it is different
mergebase=$newhash;;
refs/heads/*|HEAD)
mergebase=$(git merge-base $bref $bhash);;
esac
case $newhash,$bhash,$mergebase,$force in
$bhash,$newhash,*)
# No changes
text=" = [up to date] $bshort -> $bshort"
;;
*,*,$bhash,*)
# Fast-forward
bchanged=t
text=" $oldshort..$newshort $bshort -> $bshort"
;;
*,t)
# Forced non fast-forward
bchanged=t
text=" + $oldshort...$newshort $bshort -> $bshort (forced update)"
;;
*)
bchanged=t
nonff=t
text=" ! [rejected] $bshort -> $bshort (non-fast forward)"
esac
break
done
test -z "$text" && text=" * [$newtext] $bshort -> $bshort" && bchanged=t
if test -n "$bchanged" || test -n "$verbose"
then
test -n "$header" && echo $header && header=
echo $text
fi
test -n "$bchanged" && changed=t
done
# Recreate the bundle if --full and the current bundle is not full
test -n "$full" && bases= && test -n "$bbases" && changed=t
test -n "$nonff" && die "error: failed to push some refs to $remoteurl"
test -z "$changed" && die "Everything up-to-date"
test -n "$bases" && bases="--not$LF$bases"
git bundle create $remoteurl $refs $bases ||
die "Cannot create bundle \"$remoteurl\""
test "$remote" != "$remoteurl" && { git fetch -q "$remote" ||
die "Error fetch from bundle \"$remoteurl\"" ; }
exit 0
^ permalink raw reply
* Re: Forcing --no-ff on pull
From: Boyd Stephen Smith Jr. @ 2008-12-09 14:36 UTC (permalink / raw)
To: git; +Cc: R. Tyler Ballance
In-Reply-To: <1228819087.18611.73.camel@starfruit.local>
[-- Attachment #1: Type: text/plain, Size: 3899 bytes --]
On Tuesday 09 December 2008, "R. Tyler Ballance" <tyler@slide.com> wrote
about 'Re: Forcing --no-ff on pull':
>On Tue, 2008-12-09 at 19:17 +0900, Nanako Shiraishi wrote:
>> Quoting "R. Tyler Ballance" <tyler@slide.com>:
>> > The most common use-case involves a user merging a project branch
>> > into a stabilization branch (`git checkout stable && git pull .
>> > project`) in such a way that no merge commit is generated. Of course,
>> > without thinking they'll push these changes up to the centralized
>> > repository. Not 15 minutes later they realize "ruh roh! I didn't want
>> > to do that"
>>
>> Why does the user not want to fast-forward, if the merge she wants to
>> do is actually a fast-forward?
>
>I agree with you, this is more about preventing coworkers who are too
>lazy to understand the entirety of what they're doing from hurting the
>workflow of "the rest of us". It's a technically solution to a people
>problem (I understand technology far more than people ;))
>
>Consider the following scenarion:
> % git checkout -b project
> % <work>
> % git commit -am "A"
> % <work>
> % git commit -am "B"
> % <work>
> % git commit -am "C"
> % <work>
> % git commit -am "D"
> % git checkout stable
> % git pull . project
> % <fast-forward>
> % git push origin stable
>
>At this point, QA is involved and what can happen is that QA realizes
>that this code is *not* stable and *never* should have been brought into
>the stable branch.
>
>Now we have two options "block" the stable branch until LazyDeveloper
>makes the appropriate changes to stabilize the branch again *OR* back
>out LazyDeveloper's changes (A, B, C, D) and beat them up in the
>alleyway :)
>
>Given the nature of our work, we have a stable branch per-team, and one
>funneling stable branch for the entire company (master), that branch
>being used to push the live web site with.
In the words of 4chan: "You're doing it wrong."
If QA decides what is appropriate for the stable branch, only QA should be
pushing to stable (not just any dev. or team) and this should be enforced.
QA can retrieve commits from individual developers or teams, via email, by
pulling from their private repositories, or pulling from "private"
branches in the public repository. The last seems most appropriate for
your organization.
I think a better workflow would be for developers to pull from "stable" but
push to "<username>-tbr" (TBR = to be reviewed). Team leads would review
code by pulling from "<developer>-tbr" and if it looked okay would push
to "<team>-tbt" (TBT = to be tested). Of course, if they needed to
originate a change they could pull from "stable" instead of any individual
developer's branch. QA would pull from "<team>-tbt", build, deploy, and
test and if it's good push to "stable". Some automated process would
watch "stable" and update production from it.
This way bad commits are generally rejected before they become part of
history. Hooks can be used to notify team leads and QA about new commits
for review or testing.
>[1] We've stressed with our developers as much as possible that the
>"origin" repository is to remain" pristine", that every action should be
>"auditable" insofar that if you rollback a change, we want to see a
>Revert commit, merges should create merge commits to where we can replay
>or unwind the revision history correctly at any point in time or slice
>of time. I *really* don't want "origin" to "lose commits".
To this end, I'd probably forbid non-ff commits to "stable".
--
Boyd Stephen Smith Jr. ,= ,-_-. =.
bss03@volumehost.net ((_/)o o(\_))
ICQ: 514984 YM/AIM: DaTwinkDaddy `-'(. .)`-'
http://iguanasuicide.org/ \_/
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply
* Congratulations!!
From: DEC 2008 AWARD WINNER @ 2008-12-09 13:36 UTC (permalink / raw)
To: info
Your IDwon the sum of £1,000,000.00GBP in uk-Lottery.For claims,contact Mr.Mavel Mark Email: bnl_richardcook104@btinternet.com
Claims Form
1:Full Name
2:Country
3:Home Address
4:ocupation
5:Tel
^ permalink raw reply
* git gui: update Italian translation
From: Michele Ballabio @ 2008-12-09 13:13 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: git
In-Reply-To: <20081208163628.GG31551@spearce.org>
[-- Attachment #1: Type: text/plain, Size: 272 bytes --]
On Monday 08 December 2008, Shawn O. Pearce wrote:
> Since my last request to update translations we also picked up one
> new message string:
>
> +#: lib/transport.tcl:64
> +#, tcl-format
> +msgid "Mirroring to %s"
> +msgstr ""
> +
it.po file merged and patch attached.
[-- Attachment #2: 0001-git-gui-update-Italian-translation.patch.gz --]
[-- Type: application/x-gzip, Size: 4268 bytes --]
^ permalink raw reply
* Getting submodules to follow symlinks?
From: Jonathan del Strother @ 2008-12-09 12:55 UTC (permalink / raw)
To: Git Mailing List
My git repository contains a symlink to another repository. I'd like
to make that second repository a submodule of the first, in such a way
that when someone else clones the repository, there's no trace of the
original symlink.
Is this possible?
-Jon
^ permalink raw reply
* New script to convert p4 repositories to git - git-p4c version 1.
From: John Chapman @ 2008-12-09 10:25 UTC (permalink / raw)
To: Git Mailing List
[-- Attachment #1: Type: text/plain, Size: 1991 bytes --]
I couldn't use git-p4 on my system because I kept running out of memory,
and I didn't like the workflow it imposed.
Also, it had various other issues with the repo I was trying to use,
mainly because it is not an ideal repository, however those are
(generally) the fault of the particular repo I was using, and not
git-p4. (Which is an excellent script by itself).
This script is severely crippled in that it doesn't (yet) allow one to
contribute changesets back to perforce, however it manages to read from
perforce with:
* No need to rebase.
* Mangling of file names. (Especially with regards to case sensitivity).
* Tagging of revisions with the perforce changesets.
* Ability to handle branches with spaces in the name.
* Ability to pretend that perforce doesn't exist. (That's the plan,
anyway).
* Be extremely memory efficient. It does NOT require as much memory as
does git-p4, even when the size of the change is large.
* Be easy to manually modify the repository, particularly if bad things
happen.
Unfortunately, not all of the above features may be reliable yet,
however I offer this script in order to obtain hopefully constructive
feedback so that I may improve the script and make it work very well.
Once I perfect this script, I plan to work on getting changes from git
back into perforce, which I have a few ideas as to how I might do it.
(None of which require rebasing).
It requires an OS that can efficiently utilise many open files and
pipes, and can run many processes. Such as Linux. I seriously doubt it
can work on Windows.
It is called git-p4c, because 'git-p4' was taken, and I intended to
write it in C++. I may still rewrite it in C++ if it is found
neccessary to use it on windows. (The Perforce C++ ABI will remove the
need to fork so many processes), but I won't be doing that before I
implement the write to perforce support.
Consider this to be experimental, not yet worthy of a version number.
Remember, I crave (constructive) feedback.
Thankyou.
[-- Attachment #2: git-p4c --]
[-- Type: text/x-python, Size: 17686 bytes --]
#!/usr/bin/env python
USAGE = r'''
git-p4c - written by John Chapman.
License:
You are free to use this under the terms of the GPL License
http://www.fsf.org/licensing/licenses/gpl.html
I may change the license at any date in the future, unless
I have substantial contributions, but regardless of what licence
I choose, it will be an open source license.
Probably it will become whatever license Git itself is under,
just to make my life easier.
Example:
~/git-p4c/git-p4c \
--server=localhost:1666 \
--root=//depot \
--repo=/tmp/playground \
--user=arafangion \
--pass= \
--p4=/home/arafangion/perforce/p4 \
--max-changes=2 \
--branches='
trunk=//depot/(trunk)/(.*)
branches=//depot/branches/(.*?)/(.*)
'
'''
import datetime
import fcntl
import marshal
import os
import subprocess
import sys
import time
import sre
def main():
opts = (
'--server',
'--user',
'--pass',
'--allow-case-changes',
'--root',
'--p4',
'--branches',
'--repo',
'--initial',
'--max-changes')
config = git_config()
# Now, override configuration if specified:
for arg in sys.argv:
for opt in opts:
if arg.startswith(opt):
config[opt[2:]] = arg.split('=', 1)[1]
config = git_config(config)
P4C = p4c_Connection(config)
GIT = git_Connection(config)
start = max(int(config['initial'])-1, GIT.latest())
print 'Downloading Changesets...'
c = 0
t = time.time()
for cs in P4C.changesets(start):
if c != 0:
print 'Processing:', cs.number, 'Avg: ', (time.time()-t)/float(c), ' at', datetime.datetime.today().ctime(),
else:
print 'Processing:', cs.number,
g = GIT.commit(cs)
if g is not None:
for file in cs.files():
if file.is_interesting():
sys.stdout.write('.')
g.add(file)
sys.stdout.write('\n')
g.commit()
c += 1
if c >= int(config['max-changes']):
break
print 'Fetch Complete!'
def git_config(conf=None):
if conf is not None:
if 'repo' in conf:
try:
os.mkdir(conf['repo'])
except:
pass
os.chdir(conf['repo'])
g = subprocess.Popen(('git', 'init'))
g.wait()
for key in conf:
if '\n' in conf[key]:
c = 1
for line in conf[key].split('\n'):
line = line.strip()
if line=='':
continue
p = subprocess.Popen(('git', 'config', 'git-p4c.'+key+'-'+str(c), line))
p.wait()
c += 1
else:
p = subprocess.Popen(('git', 'config', 'git-p4c.'+key, conf[key]))
p.wait()
else:
conf = {}
p = subprocess.Popen(('git', 'config', '-l'), stdout=subprocess.PIPE)
p.wait()
conf = {}
for line in p.stdout.readlines():
line = line.strip()
if line.startswith('git-p4c.'):
key, value = line.split('=', 1)
key = key[len('git-p4c.'):]
if key.split('-')[0] == 'branches':
if 'branches' not in conf:
conf['branches'] = []
conf['branches'].append(value)
else:
conf[key] = value
# Default Values:
if 'initial' not in conf:
conf['initial'] = '0'
if 'max-changes' not in conf:
conf['max-changes'] = '999999999'
return conf
class git_Connection:
def __init__(self, config):
self._latest_mark = 1
self._latest_changeset = 0
self.config = config
self._tags = {}
cmd = ('git', 'fast-import')
self._fast_import = subprocess.Popen(cmd,
bufsize=0,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
self._prev_p4changeset = None
# Now, determine the current heads:
g = subprocess.Popen(('git', 'tag'),
stdout=subprocess.PIPE)
heads = {}
for line in g.stdout.readlines():
line = line.strip()
branch, number = unformat_tag(config, line)
if branch not in heads:
heads[branch] = [line, number]
if heads[branch][1] < number:
heads[branch][1] = number
max = 0
for head in heads:
if max < heads[head][1]:
max = heads[head][1]
tag = 'refs/tags/'+heads[head][0]
t = open('.git/'+tag, 'rb')
committish = t.read().strip()
self._record_tag(
format_tag(
self.config, head, heads[head][1]),
committish)
self._latest_changeset = max
self._heads = heads
def _record_tag(self, tag, committish):
self._tags[tag] = committish
def tag_sha1(self, tag):
return self._tags[tag]
def heads(self):
return self._heads
def latest(self):
'Returns the latest perforce changeset'
return self._latest_changeset
def commit(self, p4changeset):
return git_Commit(self, p4changeset)
def next_mark(self):
'TODO: Ensure that the latest mark in the marks file is used as the starting point.'
self._latest_mark += 1
return self._latest_mark
class git_Commit:
def __init__(self, connection, commit):
self._con = connection
self._commit = commit
self._files = {}
def add(self, p4file):
if not self._files.has_key(p4file.branch()):
self._files[p4file.branch()] = []
self._files[p4file.branch()].append(p4file)
if not p4file.action in ('delete', 'purge'):
p4file.mark = self._con.next_mark()
self._write('blob\nmark :%(mark)d\ndata %(size)d\n' % {
'mark':p4file.mark,
'size':p4file.size})
data = 'foo'
while data != '':
try:
data = p4file.read(1024)
self._write(data)
except:
time.sleep(0.1)
data = 'foo'
p4file.close_files()
def _write(self, s):
self._con._fast_import.stdin.write(s)
def commit(self):
self._mark = self._con.next_mark()
mark = self._mark
for branch in self._files.keys():
if branch in self._con.heads():
from_tag = format_tag(self._con.config, branch, self._con.heads()[branch][1])
else:
from_tag = None
self._con.heads()[branch] = [format_tag(self._con.config, branch, self._commit.number), self._commit.number]
from_branch = self._files[branch][0].orig_branch()
self._write(
'''commit %(ref)s
mark :%(mark)d
committer %(name)s <%(email)s> %(when)d +0000
data %(length)d
%(message)s
''' % {'ref':'refs/heads/'+branch,
'mark':mark,
'name':self._commit.author(),
'email':self._commit.email(),
'when':self._commit.time(),
'length':len(self._commit.commit_msg()),
'message':self._commit.commit_msg()})
if branch != from_branch:
self._write(
'from %(from)s\n' %
{'from':'refs/heads/'+from_branch})
elif from_tag is not None:
self._write(
'from %(from)s\n' %
{'from':self._con.tag_sha1(from_tag)})
for file in self._files[branch]:
if file.action in ('add', 'edit', 'integrate', 'branch'):
self._c_add(file)
elif file.action in ('delete', 'purge'):
self._c_delete(file)
else:
print 'Unhandled action:', file
tagname = format_tag(self._con.config, branch, self._commit.number)
self._write(
'''tag %(tagname)s
from %(committish)s
tagger %(name)s <%(email)s> %(when)d +0000
data 0
''' % {
'tagname':tagname,
'committish':':'+str(mark),
'name':self._commit.author(),
'email':self._commit.email(),
'when':self._commit.time()})
self._con._record_tag(tagname, ':'+str(mark))
def _c_add(self, file):
self._write(
'''M 100644 :%(mark)d %(path)s\n''' % {
'path':file.name(),
'mark':file.mark})
def _c_delete(self, file):
self._write('D %(path)s\n' % {'path':file.name()})
class p4c_Connection:
def __init__(self, details):
self._p4_exe = details['p4']
self._p4port = details['server']
self.config = details
self._users = None
def _p4(self, args):
return subprocess.Popen(
(self._p4_exe,)+args,
bufsize=0,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env={'P4PORT':self._p4port,'P4PASSWD':self.config['pass'],'P4USER':self.config['user']},
close_fds=True)
def user(self, username):
if self._users is None:
p = self._p4(('-G', 'users'))
try:
self._users = {}
while True:
d = marshal.load(p.stdout)
self._users[username] = {}
self._users[username]['email'] = d['Email']
self._users[username]['name'] = d['FullName']
except EOFError, e:
pass
try:
return self._users[username]
except:
return {'email':'Not A Current P4 User', 'name':username}
def changesets(self, start):
if self.config['root'][-1] != '/':
self.config['root'] += '/'
p = self._p4(('-G', 'changes', '-l', '-t', self.config['root']+'...'))
try:
self._changesets = []
while True:
d = marshal.load(p.stdout)
self._changesets.append((int(d['change']), int(d['time'])))
except EOFError, e:
pass
def s(x, y):
if x[1] < y[1]: return -1
if x[1] > y[1]: return 1
return 0
self._changesets.sort(s)
for change, time in self._changesets:
if change > start:
yield self._Changeset(self, change, time)
class _File:
def __init__(self, connection, details):
self._connection = connection
self._details = details
self.action = self._details['action']
p = self._connection._p4(('-G', 'sizes', self.p4name()))
try:
if not self.action in ('delete', 'purge'):
self.size = marshal.load(p.stdout)
self.size = int(self.size['fileSize'])
except Exception, e:
self.size = 0
self.action = 'purge'
self._p = self._connection._p4(('print', '-q', self.p4name()))
self.read = self._p.stdout.read
oldflags = fcntl.fcntl(self._p.stdout, fcntl.F_GETFL)
fcntl.fcntl(self._p.stdout, fcntl.F_SETFL, oldflags|os.O_NONBLOCK)
try:
self._branch_name, self._orig_branch, self._name = on_branch(self._connection.config, self.p4name())
except:
self._branch_name = None
self._orig_branch = None
self._name = None
def p4name(self):
return '//'+self._details['file']+'#'+self.rev()
def branch(self):
return self._branch_name
def orig_branch(self):
return self._orig_branch
def name(self):
return self._name
def is_interesting(self):
return self._branch_name is not None
def rev(self):
return self._details['rev']
def tag(self):
print self
return self._details['tag']
def __str__(self):
return '\t'.join([key+' '+self._details[key] for key in self._details.keys()])
def __del__(self):
if self.read is not None:
self.close_files()
def close_files(self):
self.read = None
self._p.stdout.close()
self._p.stderr.close()
self._p.stdin.close()
self._p.wait()
del self._p
class _Changeset:
def __init__(self, connection, number, time):
self.number = number
self._time = time
self._connection = connection
self._desc = {}
self._files = {}
p = self._connection._p4(('-G', 'describe', str(self.number)))
try:
d = marshal.load(p.stdout)
for key in d.keys():
if key[-1] in '0123456789':
'Is referring to a particular file.'
num = 0
name = ''
for c in key:
if c in '0123456789':
num *= 10
num += int(c)
else:
name += c
if not self._files.has_key(num):
self._files[num] = {}
'TODO: Determine which branch(es) this file belongs to.'
if name == 'depotFile':
self._files[num]['file'] = d[key][2:]
else:
self._files[num][name] = d[key]
self._files[num][name] = d[key]
else:
self._desc[key] = d[key]
except EOFError, e:
pass
def __str__(self):
return 'Changeset: %s Time: %s' % (self.number, self.time)
def commit_msg(self):
return self._desc['desc']
def author(self):
return self._connection.user(self._desc['client'])['name']+" '"+self._desc['client']+"'"
def email(self):
return self._connection.user(self._desc['client'])['email']
def time(self):
return self._time
def files(self):
for number in self._files.keys():
yield self._connection._File(self._connection, self._files[number])
_seen = None
_tree = None
def generate_tree():
'''Reads the current git repo and iterates over every branch, reading all files and
directories, in order to ensure that file case does not ever change'''
def get_branches():
p = subprocess.Popen(('git', 'branch'), stdout=subprocess.PIPE)
p.wait()
for line in p.stdout.readlines():
yield line.strip()
def get_ls_tree(BranchOrSha1, dir=''):
'''This function is very recursive,
it returns ALL the trees (ie, the directories).'''
p = subprocess.Popen(('git', 'ls-tree', BranchOrSha1), stdout=subprocess.PIPE)
p.wait()
for line in p.stdout.readlines():
items = [item.strip() for item in line.strip().split(' ', 2)]
last = items[-1]
del items[-1]
split_items = last.split('\t', 1)
items.append(split_items[0])
items.append(dir+split_items[1]+'/')
if items[1] == 'tree':
yield items
for item in get_ls_tree(items[2], items[-1]):
yield item
global _tree
_tree = {}
for branch in get_branches():
for items in get_ls_tree(branch):
_tree[items[-1][:-1].lower()] = items[-1][:-1].split('/')[-1]
def mangle_case(config, file):
components = file.split('/')
for i in range(len(components)-1):
part = '/'.join(components[:i+1]).lower()
if part in _tree:
components[i] = _tree[part]
else:
_tree['/'.join(components[:i+1])] = components[i]
file = '/'.join(components)
return file
def on_branch(config, p4_filename):
# TODO: Need to change this so that:
# * If desired, prevent changes in case, either by simply preventing changes in case,
# or also by using an 'authoritative' perforce changeset.
# * Stop using the stupid global for _seen, and consult the repo.
# (Currently it's worse than nothing, because
# it stuffs up the parent commits.)
global _seen
if _tree is None:
generate_tree()
if _seen is None:
_seen = {}
p = subprocess.Popen(('git', 'branch'), stdout=subprocess.PIPE)
for line in p.stdout.readlines():
_seen[line.strip()] = None
p.wait()
first=None
for b in config['branches']:
b, p = b.split('=', 1)
if first is None:
first = b
m = sre.match('^'+p+'\#.*$', p4_filename)
if m:
branch, file = m.groups()
if branch in _seen:
return branch, branch, mangle_case(config, file)
else:
_seen[branch] = None
return branch, first, mangle_case(config, file)
def format_tag(config, branch, number):
return branch+'/'+str(number)
def unformat_tag(config, tag):
branch, number = tag.rsplit('/', 1)
number = int(number)
return branch, number
if __name__ == '__main__':
main()
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox