* Re: [RFC] Automagic patch merge ack emails
From: Boyd Stephen Smith Jr. @ 2008-12-22 20:59 UTC (permalink / raw)
To: git; +Cc: Richard Hartmann
In-Reply-To: <2d460de70812220607j7f218ee3r7722bc8147a3dab4@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1475 bytes --]
On Monday 2008 December 22 08:07:07 Richard Hartmann wrote:
> I poked around the docs, but I could not find any option to have git
> send email to people who signed off a patch when it's merged.
There's not one, since something that that should probably be done in a hook.
Maybe the update hook?
> I only realized the two patches I sent were merged because they were
> listed in the RC changelog summary and would have followed up my patch
> email in a about a week, asking about its status.
>
> Does anyone else think this is useful?
I think it would be nice to get a notification whenever Junio pushes commits
to 'master' or 'maint' in git.git if I've signed off on one of the commits.
I don't think everyone would though so the hook would need to be maintained
indefinitely (updating the email blacklist, etc.).
It would probably be a nice hook to have as an example, I guess.
> Does anyone else think it should
> make it into main so it can be enabled via config, not via a hook that
> needs to be imported into each and every repo?
Definitely not. It's not that difficult to add a hook to the repositories
that need it, and I think the majority of repositories will be private and
not need it.
--
Boyd Stephen Smith Jr. ,= ,-_-. =.
bss@iguanasuicide.net ((_/)o o(\_))
ICQ: 514984 YM/AIM: DaTwinkDaddy `-'(. .)`-'
http://iguanasuicide.net/ \_/
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply
* Re: [PATCH 2/2] rebase -i -p: Fix --continue after a merge could not be redone
From: Johannes Schindelin @ 2008-12-22 21:06 UTC (permalink / raw)
To: Johannes Sixt; +Cc: Junio C Hamano, Andreas Ericsson, Stephen Haberman, git
In-Reply-To: <1229335531-32707-2-git-send-email-j6t@kdbg.org>
Hi,
On Mon, 15 Dec 2008, Johannes Sixt wrote:
> When a merge that has a conflict was rebased, then rebase stopped to let
> the user resolve the conflicts. However, thereafter --continue failed
> because the author-script was not saved. (This is rebase -i's way to
> preserve a commit's authorship.) This fixes it by doing taking the same
> failure route after a merge that is also taken after a normal cherry-pick.
>
> Signed-off-by: Johannes Sixt <j6t@kdbg.org>
> ---
> This is an attempt at fixing the failure. I don't know whether it is
> problematic to leave a "patch" behind if there was actually a merge.
I'd suggest leaving behind a --cc patch, so that nobody is tempted to
"fix" the patch until it applies.
> diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
> index 1172e47..89c39eb 100755
> --- a/git-rebase--interactive.sh
> +++ b/git-rebase--interactive.sh
> @@ -253,15 +253,14 @@ pick_one_preserving_merges () {
> if ! GIT_AUTHOR_NAME="$GIT_AUTHOR_NAME" \
> GIT_AUTHOR_EMAIL="$GIT_AUTHOR_EMAIL" \
> GIT_AUTHOR_DATE="$GIT_AUTHOR_DATE" \
> output git merge $STRATEGY -m "$msg" \
> $new_parents
> then
> - git rerere
Why? I found rerere pretty helpful when rebasing merges.
Ah, it is done by die_with_patch() already. You might want to prevent
headscratching and hunting around for a few minutes, by simply mentioning
that fact in the commit message.
I'll leave the commit message fixing to you, but the --cc patch probably
looks something like this -- feel free to squash in:
---
git-rebase--interactive.sh | 18 +++++++++++++++---
1 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 89c39eb..b20c101 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -115,9 +115,21 @@ mark_action_done () {
}
make_patch () {
- parent_sha1=$(git rev-parse --verify "$1"^) ||
- die "Cannot get patch for $1^"
- git diff-tree -p "$parent_sha1".."$1" > "$DOTEST"/patch
+ sha1_and_parents="$(git rev-list --parents -1 $1)"
+ case "$sha1_and_parents" in
+ *' '*' '*' '*)
+ echo "Octopus merge"
+ ;;
+ *' '*' '*)
+ git diff --cc $sha1_and_parents
+ ;;
+ *' '*)
+ git diff-tree -R -p $sha1_and_parents
+ ;;
+ *)
+ echo "Root commit"
+ ;;
+ esac > "$DOTEST"/patch
test -f "$DOTEST"/message ||
git cat-file commit "$1" | sed "1,/^$/d" > "$DOTEST"/message
test -f "$DOTEST"/author-script ||
^ permalink raw reply related
* Re: [PATCH 2/2] rebase -i -p: Fix --continue after a merge could not be redone
From: Johannes Schindelin @ 2008-12-22 21:16 UTC (permalink / raw)
To: Johannes Sixt; +Cc: Junio C Hamano, Andreas Ericsson, Stephen Haberman, git
In-Reply-To: <alpine.DEB.1.00.0812222139340.30769@pacific.mpi-cbg.de>
Hi,
On Mon, 22 Dec 2008, Johannes Schindelin wrote:
> I'll leave the commit message fixing to you, but the --cc patch probably
> looks something like this -- feel free to squash in:
>
> ---
> [... a patch ...]
Ooops. Scratch that. I tested without running the test suite, and sure
enough, it failed. Take that instead.
--
git-rebase--interactive.sh | 18 +++++++++++++++---
1 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 89c39eb..f08409c 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -115,9 +115,21 @@ mark_action_done () {
}
make_patch () {
- parent_sha1=$(git rev-parse --verify "$1"^) ||
- die "Cannot get patch for $1^"
- git diff-tree -p "$parent_sha1".."$1" > "$DOTEST"/patch
+ sha1_and_parents="$(git rev-list --parents -1 $1)"
+ case "$sha1_and_parents" in
+ *' '*' '*' '*)
+ echo "Octopus merge"
+ ;;
+ *' '*' '*)
+ git diff --cc $sha1_and_parents
+ ;;
+ *' '*)
+ git diff-tree -p $1^!
+ ;;
+ *)
+ echo "Root commit"
+ ;;
+ esac > "$DOTEST"/patch
test -f "$DOTEST"/message ||
git cat-file commit "$1" | sed "1,/^$/d" > "$DOTEST"/message
test -f "$DOTEST"/author-script ||
^ permalink raw reply related
* Re: 'Theirs' merge between branches on a binary file.
From: Junio C Hamano @ 2008-12-22 21:11 UTC (permalink / raw)
To: Tim Visher; +Cc: git
In-Reply-To: <c115fd3c0812221256l494bb824ga8e1640efb07b20c@mail.gmail.com>
"Tim Visher" <tim.visher@gmail.com> writes:
> I have a binary file that is coming up with a merge conflict
> (obviously) between two branches and I want to simply say, 'take their
> version of the file'.
Do you mean during a conflicted merge resolution you would want to check
their version out of the index and declare that it is the merge result?
^ permalink raw reply
* Re: 'Theirs' merge between branches on a binary file.
From: Tim Visher @ 2008-12-22 21:16 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vr63zhq4k.fsf@gitster.siamese.dyndns.org>
On Mon, Dec 22, 2008 at 4:11 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Do you mean during a conflicted merge resolution you would want to check
> their version out of the index and declare that it is the merge result?
Sure. Let me try to be a bit clearer.
I was developing on a feature branch and now want to merge back into
the master branch. Unfortunately, a binary file somewhat central to
the development effort was changed between the the feature branch and
the master branch and now there is a conflict. Obviously, I can't fix
the conflict via markers or something like that because it's a binary
file, and I know that I want the feature branch's version of the file,
not the one that it is in conflict with. How would I just select the
stage3 version of the file and add that to the index?
--
In Christ,
Timmy V.
http://burningones.com/
http://five.sentenc.es/ - Spend less time on e-mail
^ permalink raw reply
* Re: Bugs in sub argsfromdir of git-cvsserver
From: Le @ 2008-12-22 21:42 UTC (permalink / raw)
To: Git Mailing List
In-Reply-To: <494FF9A9.9060706@distributel.ca>
Le wrote:
> Hi, all,
>
> I found a bug in git-cvsserver.
> sub argsfromdir
> {
>
> if ( scalar(@{$state->{args}}) == 1 )
> {
> my $arg = $state->{args}[0];
> #$arg .= $state->{prependdir} if ( defined (
> $state->{prependdir} ) );
> $arg = $state->{prependdir} . $arg if ( defined (
> $state->{prependdir} ) );
> $log->info("Only one arg specified, checking for directory
> expansion on '$arg'");
> ...
> }
> ...
> }
>
> It makes not sense of the above remarked out code.
>
> But when I use the code followed remarked out, I have problem to use
> cvs diff or cvs log in a sub directory of the root (may other commands
> as well). Eg.:
>
> I have a project called test1 and in test1 there is a test2
> subdirectory and a file test2/test3.txt.
> I have no problem to cvs diff and cvs log in test1 directory. But if I
> enter test1/test2 to check these commands then they are not working.
>
> I tried to fixed the problem to remarked out the code:
> #$filename = filecleanup($filename);
> in req_log and req_diff, then both cvs diff and cvs log work.
>
> In
> sub filecleanup
> {
> ...
> $filename = $state->{prependdir} . $filename;
> return $filename;
> }
>
> inserts $state->{prependdir} into the $filename.
>
> But I don't know if what I did brings incompatibilities.
>
> Can anybody check this issue?
>
> Thanks!
>
> Le Wen
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
It seems that req_up and req_status need to be changed as well. I am not
which subs need to be changed.
Le Wen
^ permalink raw reply
* Merge two repos with history included? (was Re: How do I..?)
From: Dylan Martin @ 2008-12-22 22:04 UTC (permalink / raw)
To: git
I tried converting an existing SVN repo to git and then adding it to
my main git repo using the subtree merge technique described at
http://www.kernel.org/pub/software/scm/git/docs/howto/using-merge-subtree.html.
I now have the various files in my repo, but they have no history.
I checked, and my initial SVN to git conversion does contain history.
I'm trying to add an exising repo as a subdir of my main repo with
history included. Can anyone tell me how to do that?
I'm sorry if I'm phrasing my question badly, or if I'm asking
something that should be obvious...
Thanks!
-Dylan
On Wed, Dec 17, 2008 at 3:49 PM, Miklos Vajna <vmiklos@frugalware.org> wrote:
> On Wed, Dec 17, 2008 at 03:16:59PM -0800, Dylan Martin <dmartin@sccd.ctc.edu> wrote:
>> Sorry if this is a dumb question. I've poked around the docs and
>> tried the google searches I could think of, but I don't even know what
>> kind of search terms one would use in trying to answer this.
>>
>> I'm a sysadmin and I've got a big monolithic git repo of all my
>> scripts, documents, etc... It used to be a CVS repo but I converted
>> it to git a while ago.
>> Before I switched to git, I played around with SVN a bit, and started
>> a few tiny SVN repos for various scripts I was working on. So, I know
>> have one git repo with %90 of my stuff and a handful of SVN repos.
>> I'd like to be able to add the SVN repos as subdirectories inside my
>> git repo. I've found lots of pages describing how to convert an SVN
>> repo into a _new_ git repo, but I haven't found anything yet about
>> importing the contents of an SVN repo as a subdirectory of an
>> _existing_ git repo.
>
> I would convert each repo to git, then merge them using subtree merge.
> See Documentation/howto/using-merge-subtree.txt.
>
^ permalink raw reply
* [PATCH] merge-recursive: mark rename/delete conflict as unmerged
From: Johannes Schindelin @ 2008-12-22 22:10 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Constantine Plotnikov, git, Alex Riesen
In-Reply-To: <7v4p0whr7a.fsf@gitster.siamese.dyndns.org>
When a file was renamed in one branch, but deleted in the other, one
should expect the index to contain an unmerged entry, namely the
target of the rename. Make it so.
Noticed by Constantine Plotnikov.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
On Mon, 22 Dec 2008, Junio C Hamano wrote:
> "Constantine Plotnikov" <constantine.plotnikov@gmail.com> writes:
>
> > I think that if git merge reports the conflicts, such
> > conflicts should be discoverable using git ls-files and prevent
> > commit with resolving the conflict like it is done with
> > modify-delete conflicts.
>
> Yeah, I think so, too.
A test case would have been nice.
merge-recursive.c | 5 +++++
t/t6024-recursive-merge.sh | 23 +++++++++++++++++++++++
2 files changed, 28 insertions(+), 0 deletions(-)
diff --git a/merge-recursive.c b/merge-recursive.c
index a0c804c..69e7152 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -902,6 +902,11 @@ static int process_renames(struct merge_options *o,
ren1_src, ren1_dst, branch1,
branch2);
update_file(o, 0, ren1->pair->two->sha1, ren1->pair->two->mode, ren1_dst);
+ update_stages(ren1_dst, NULL,
+ branch1 == o->branch1 ?
+ ren1->pair->two : NULL,
+ branch1 == o->branch1 ?
+ NULL : ren1->pair->two, 1);
} else if (!sha_eq(dst_other.sha1, null_sha1)) {
const char *new_path;
clean_merge = 0;
diff --git a/t/t6024-recursive-merge.sh b/t/t6024-recursive-merge.sh
index 802d0d0..129fa30 100755
--- a/t/t6024-recursive-merge.sh
+++ b/t/t6024-recursive-merge.sh
@@ -97,4 +97,27 @@ test_expect_success 'refuse to merge binary files' '
merge.err
'
+test_expect_success 'mark rename/delete as unmerged' '
+
+ git reset --hard &&
+ git checkout -b delete &&
+ git rm a1 &&
+ test_tick &&
+ git commit -m delete &&
+ git checkout -b rename HEAD^ &&
+ git mv a1 a2
+ test_tick &&
+ git commit -m rename &&
+ test_must_fail git merge delete &&
+ test 1 = $(git ls-files --unmerged | wc -l) &&
+ git rev-parse --verify :2:a2 &&
+ test_must_fail git rev-parse --verify :3:a2 &&
+ git checkout -f delete &&
+ test_must_fail git merge rename &&
+ test 1 = $(git ls-files --unmerged | wc -l) &&
+ test_must_fail git rev-parse --verify :2:a2 &&
+ git rev-parse --verify :3:a2
+
+'
+
test_done
--
1.6.1.rc3.412.ga72b
^ permalink raw reply related
* Re: 'Theirs' merge between branches on a binary file.
From: Junio C Hamano @ 2008-12-22 22:52 UTC (permalink / raw)
To: Tim Visher; +Cc: git
In-Reply-To: <c115fd3c0812221316y24ce0c7q29807cd349a99e83@mail.gmail.com>
"Tim Visher" <tim.visher@gmail.com> writes:
> On Mon, Dec 22, 2008 at 4:11 PM, Junio C Hamano <gitster@pobox.com> wrote:
>
>> Do you mean during a conflicted merge resolution you would want to check
>> their version out of the index and declare that it is the merge result?
>
> Sure.
That sounds like "git checkout --theirs"...
^ permalink raw reply
* Re: 'Theirs' merge between branches on a binary file.
From: Tim Visher @ 2008-12-22 22:58 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vd4fjhlf8.fsf@gitster.siamese.dyndns.org>
On Mon, Dec 22, 2008 at 5:52 PM, Junio C Hamano <gitster@pobox.com> wrote:
> That sounds like "git checkout --theirs"...
I'm sorry, Junio. I don't mean to be dense but I can't find that in
the docs and when I execute it it comes back as an unknown command.
Perhaps you could just point me to the relevant man page? This seems
like such a fundamental operation, I just don't understand why there
isn't something like a `git resolve`.
Thanks for your help!
--
In Christ,
Timmy V.
http://burningones.com/
http://five.sentenc.es/ - Spend less time on e-mail
^ permalink raw reply
* Re: [PATCH] merge-recursive: mark rename/delete conflict as unmerged
From: Junio C Hamano @ 2008-12-22 23:12 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Constantine Plotnikov, git, Alex Riesen
In-Reply-To: <alpine.DEB.1.00.0812222308410.30769@pacific.mpi-cbg.de>
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> When a file was renamed in one branch, but deleted in the other, one
> should expect the index to contain an unmerged entry, namely the
> target of the rename. Make it so.
That was quick, but the surrounding code makes me wonder if other
if/elseif branches also need similar handling.
For example, rename/add comes up with a new name that does not exist
anywhere, and adds both to the index; it is understandable that you need
to do this when processing a merge with non-zero depth because you need to
have a tree as the result, but shouldn't the final zero depth merge just
use the original names and leave the results in higher stages?
^ permalink raw reply
* Re: 'Theirs' merge between branches on a binary file.
From: Junio C Hamano @ 2008-12-22 23:18 UTC (permalink / raw)
To: Tim Visher; +Cc: git
In-Reply-To: <c115fd3c0812221458q3444cbcai7ab1716b9195ad08@mail.gmail.com>
"Tim Visher" <tim.visher@gmail.com> writes:
> On Mon, Dec 22, 2008 at 5:52 PM, Junio C Hamano <gitster@pobox.com> wrote:
>
>> That sounds like "git checkout --theirs"...
>
> I'm sorry, Junio. I don't mean to be dense but I can't find that in
> the docs and when I execute it it comes back as an unknown command.
Hmph, I meant to point you at:
http://www.kernel.org/pub/software/scm/git/docs/git-checkout.html
I think you can use "git checkout-index --stage=3 path" if your git is
older than that one with the option.
v1.6.0.1-15-g38901a4 (checkout --ours/--theirs: allow checking out one
side of a conflicting merge, 2008-08-30) introduced the feature.
^ permalink raw reply
* Re: Perl 5 now uses Git for version control
From: Daniel Barkalow @ 2008-12-22 23:24 UTC (permalink / raw)
To: demerphq; +Cc: git
In-Reply-To: <9b18b3110812220332u4cae3a89rf957cbf96af530bf@mail.gmail.com>
On Mon, 22 Dec 2008, demerphq wrote:
> In true open source style, Sam Vilain converted Perl's history from
> Perforce to Git. He did the work both in his spare time and in time
> donated by his employer, Catalyst IT. He spent more than a year building
> custom tools to transform 21 years of Perl history into the first
> ever unified repository of every single change to Perl. In addition
> to changes from Perforce, Sam patched together a comprehensive view
> of Perl's history incorporating publicly available snapshot releases,
> changes from historical mailing list archives and patch sets recovered
> from the hard drives of previous Perl release engineers.
At some point, some of the custom tools were visible to the public
(although not widely announced), and they include such things as an
elaborate algorithm to figure out what a perforce depot's contents is
supposed to mean in a number of weird cases. Are these going to be
officially released, or are they considered to have served their purpose
and be no longer interesting?
I'd be interested to see the final version, and I think it would be useful
to anyone working on interoperation between perforce and git (even though
the actual code needs a copy of the perforce database and is not
incremental).
-Daniel
*This .sig left intentionally blank*
^ permalink raw reply
* [JGIT PATCH 00/13] Add receive-pack server side support
From: Shawn O. Pearce @ 2008-12-23 0:27 UTC (permalink / raw)
To: Robin Rosenberg; +Cc: git
This is a simple implementation of the receive-pack part of the
send-pack/receive-pack protocol used by push. Most of the logic
the server implements can be customized by implementing your
own PreReceiveHook implementation.
I'm actually going to use this within Gerrit 2 so users can push
into the special ref name "refs/changes/new" and have an anonymous
topic branch be created instead.
A basic "jgit daemon" for the git:// protocol is also included.
This daemon still has some major limitations over "git daemon":
- Only "receive-pack" is supported. We do not have a Java
version of "upload-pack" so we do not support it here.
- Virtual hosting is not supported; the "host=" header (if sent
by the client) is discarded.
- User escapes ("git://host/~user/foo.git") are not honored.
- No receive timeouts. Evil clients can connect and do nothing,
pinning the server thread indefinitely. This can cause the
server to consume resources until it crashes.
- No connection limits. Evil clients can DOS the server by just
opening a ton of connections.
- "jgit daemon" must be started within a git repository, even if
it won't publish that repository over the network. This is due
to a limitation in the way TextBuiltin initializes itself.
Providing "jgit receive-pack" should be trivial if the last item
is fixed, permitting jgit commands to be executed from outside of
a Git repository.
JSch does not have an SSH server implementation, so we cannot easily
provide an SSH daemon for our new push support. Apache MINA SSHD has
a nice daemon under development, and I plan on using it in Gerrit 2.
Perhaps someone will eventually contribute an extension library
for JGit which provides the binding glue necessary for MINA SSHD
to invoke JGit.
JGit's ReceivePack class does not invoke the standard hooks honored
by "git receive-pack", because doing so would require executing
an external process. There's enough data available in memory that
someone could easily contribute a PreReceiveHook and PostRecieveHook
implementation that honored these.
The early part of the series has some code cleanups to ensure we
are thread-safe, and to reduce the thrasing on the InflaterCache.
Shawn O. Pearce (13):
Fix invalid "double checked locking" in InflaterCache
Cleanup stupid release of the cached Inflater in IndexPack
Cache an Inflater inside a WindowCursor and reuse it as much as
possible
Make RefDatabase thread-safe
Make PackFile thread-safe
Make Repository thread-safe
Don't open a PackFile multiple times on scanForPacks
Expose RepositoryConfig.getBoolean so applications can use it
Add AnyObjectId.copyTo(StringBuilder)
Add compare-and-swap semantics to RefUpdate
Allow null new ObjectId during RefUpdate.delete
Implement the git-receive-pack process in Java
Add basic git daemon support to publish receive-pack
.../services/org.spearce.jgit.pgm.TextBuiltin | 1 +
.../src/org/spearce/jgit/pgm/Daemon.java | 125 +++
.../src/org/spearce/jgit/lib/AnyObjectId.java | 17 +-
.../jgit/lib/DeltaRefPackedObjectLoader.java | 2 +-
.../src/org/spearce/jgit/lib/InflaterCache.java | 31 +-
.../src/org/spearce/jgit/lib/PackFile.java | 14 +-
.../src/org/spearce/jgit/lib/RefDatabase.java | 29 +-
.../src/org/spearce/jgit/lib/RefUpdate.java | 32 +-
.../src/org/spearce/jgit/lib/Repository.java | 90 ++-
.../src/org/spearce/jgit/lib/RepositoryConfig.java | 4 +-
.../src/org/spearce/jgit/lib/WindowCursor.java | 33 +-
.../src/org/spearce/jgit/lib/WindowedFile.java | 17 +-
.../src/org/spearce/jgit/revwalk/RevWalk.java | 4 +-
.../src/org/spearce/jgit/transport/Daemon.java | 309 ++++++++
.../org/spearce/jgit/transport/DaemonClient.java | 106 +++
.../org/spearce/jgit/transport/DaemonService.java | 120 +++
.../src/org/spearce/jgit/transport/IndexPack.java | 17 +-
.../org/spearce/jgit/transport/PacketLineIn.java | 12 +
.../spearce/jgit/transport/PostReceiveHook.java | 77 ++
.../org/spearce/jgit/transport/PreReceiveHook.java | 94 +++
.../org/spearce/jgit/transport/ReceiveCommand.java | 223 ++++++
.../org/spearce/jgit/transport/ReceivePack.java | 793 ++++++++++++++++++++
.../spearce/jgit/transport/TransportGitAnon.java | 3 +-
23 files changed, 2060 insertions(+), 93 deletions(-)
create mode 100644 org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Daemon.java
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/transport/Daemon.java
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/transport/DaemonClient.java
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/transport/DaemonService.java
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/transport/PostReceiveHook.java
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/transport/PreReceiveHook.java
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/transport/ReceiveCommand.java
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/transport/ReceivePack.java
^ permalink raw reply
* [JGIT PATCH 02/13] Cleanup stupid release of the cached Inflater in IndexPack
From: Shawn O. Pearce @ 2008-12-23 0:27 UTC (permalink / raw)
To: Robin Rosenberg; +Cc: git
In-Reply-To: <1229992043-1053-2-git-send-email-spearce@spearce.org>
The try/finally idiom avoids placing the Inflater on the stack,
which means it goes unreachable slightly faster. Its also much
less obtuse to read.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
.../src/org/spearce/jgit/transport/IndexPack.java | 8 +++++---
1 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java b/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java
index 2752bb0..3e2187c 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java
@@ -320,9 +320,11 @@ public void index(final ProgressMonitor progress) throws IOException {
writeIdx();
} finally {
- final Inflater inf = inflater;
- inflater = null;
- InflaterCache.release(inf);
+ try {
+ InflaterCache.release(inflater);
+ } finally {
+ inflater = null;
+ }
progress.endTask();
if (packOut != null)
--
1.6.1.rc4.301.g5497a
^ permalink raw reply related
* [JGIT PATCH 01/13] Fix invalid "double checked locking" in InflaterCache
From: Shawn O. Pearce @ 2008-12-23 0:27 UTC (permalink / raw)
To: Robin Rosenberg; +Cc: git
In-Reply-To: <1229992043-1053-1-git-send-email-spearce@spearce.org>
We move the Inflater allocation out of the synchronized block as
it requires JNI code to build the libz structure. This permits
other threads to get into the Inflater allocation faster.
We also fix the release implementation to validate the array size
only after we enter the lock, rather than before. This prevents
us from releasing an inflater due to a stale copy of the open
count being in our processor cache.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
.../src/org/spearce/jgit/lib/InflaterCache.java | 31 ++++++++++---------
1 files changed, 16 insertions(+), 15 deletions(-)
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/InflaterCache.java b/org.spearce.jgit/src/org/spearce/jgit/lib/InflaterCache.java
index f0f9139..578911c 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/InflaterCache.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/InflaterCache.java
@@ -59,13 +59,18 @@
*
* @return an available inflater. Never null.
*/
- public synchronized static Inflater get() {
+ public static Inflater get() {
+ final Inflater r = getImpl();
+ return r != null ? r : new Inflater(false);
+ }
+
+ private synchronized static Inflater getImpl() {
if (openInflaterCount > 0) {
final Inflater r = inflaterCache[--openInflaterCount];
inflaterCache[openInflaterCount] = null;
return r;
}
- return new Inflater(false);
+ return null;
}
/**
@@ -76,23 +81,19 @@ public synchronized static Inflater get() {
* does nothing.
*/
public static void release(final Inflater i) {
- if (i == null)
- return;
-
- if (openInflaterCount == SZ) {
- i.end();
- return;
+ if (i != null) {
+ i.reset();
+ if (releaseImpl(i))
+ i.end();
}
-
- i.reset();
- releaseImpl(i);
}
- private static synchronized void releaseImpl(final Inflater i) {
- if (openInflaterCount == SZ)
- i.end();
- else
+ private static synchronized boolean releaseImpl(final Inflater i) {
+ if (openInflaterCount < SZ) {
inflaterCache[openInflaterCount++] = i;
+ return false;
+ }
+ return true;
}
private InflaterCache() {
--
1.6.1.rc4.301.g5497a
^ permalink raw reply related
* [JGIT PATCH 04/13] Make RefDatabase thread-safe
From: Shawn O. Pearce @ 2008-12-23 0:27 UTC (permalink / raw)
To: Robin Rosenberg; +Cc: git
In-Reply-To: <1229992043-1053-4-git-send-email-spearce@spearce.org>
This is necessary to support a thread-safe Repository.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
.../src/org/spearce/jgit/lib/RefDatabase.java | 29 +++++++++++---------
1 files changed, 16 insertions(+), 13 deletions(-)
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java
index 4cf6e08..87f26bf 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java
@@ -93,7 +93,7 @@ RefDatabase(final Repository r) {
clearCache();
}
- void clearCache() {
+ synchronized void clearCache() {
looseRefs = new HashMap<String, Ref>();
looseRefsMTime = new HashMap<String, Long>();
packedRefs = new HashMap<String, Ref>();
@@ -139,9 +139,11 @@ RefUpdate newUpdate(final String name) throws IOException {
}
void stored(final String origName, final String name, final ObjectId id, final long time) {
- looseRefs.put(name, new Ref(Ref.Storage.LOOSE, origName, name, id));
- looseRefsMTime.put(name, time);
- setModified();
+ synchronized (this) {
+ looseRefs.put(name, new Ref(Ref.Storage.LOOSE, origName, name, id));
+ looseRefsMTime.put(name, time);
+ setModified();
+ }
db.fireRefsMaybeChanged();
}
@@ -157,11 +159,13 @@ void stored(final String origName, final String name, final ObjectId id, final l
void link(final String name, final String target) throws IOException {
final byte[] content = Constants.encode("ref: " + target + "\n");
lockAndWriteFile(fileForRef(name), content);
- setModified();
+ synchronized (this) {
+ setModified();
+ }
db.fireRefsMaybeChanged();
}
- void setModified() {
+ private void setModified() {
lastRefModification = refModificationCounter++;
}
@@ -210,7 +214,7 @@ Ref readRef(final String partialName) throws IOException {
return avail;
}
- private void readPackedRefs(final Map<String, Ref> avail) {
+ private synchronized void readPackedRefs(final Map<String, Ref> avail) {
refreshPackedRefs();
avail.putAll(packedRefs);
}
@@ -229,7 +233,7 @@ private void readLooseRefs(final Map<String, Ref> avail,
}
}
- private void readOneLooseRef(final Map<String, Ref> avail,
+ private synchronized void readOneLooseRef(final Map<String, Ref> avail,
final String origName, final String refName, final File ent) {
// Unchanged and cached? Don't read it again.
//
@@ -323,8 +327,8 @@ private Ref readRefBasic(final String name, final int depth) throws IOException
return readRefBasic(name, name, depth);
}
- private Ref readRefBasic(final String origName, final String name, final int depth)
- throws IOException {
+ private synchronized Ref readRefBasic(final String origName,
+ final String name, final int depth) throws IOException {
// Prefer loose ref to packed ref as the loose
// file can be more up-to-date than a packed one.
//
@@ -408,7 +412,7 @@ private Ref readRefBasic(final String origName, final String name, final int dep
return ref;
}
- private void refreshPackedRefs() {
+ private synchronized void refreshPackedRefs() {
final long currTime = packedRefsFile.lastModified();
final long currLen = currTime == 0 ? 0 : packedRefsFile.length();
if (currTime == packedRefsLastModified && currLen == packedRefsLength)
@@ -479,7 +483,7 @@ private void lockAndWriteFile(File file, byte[] content) throws IOException {
throw new ObjectWritingException("Unable to write " + name);
}
- void removePackedRef(String name) throws IOException {
+ synchronized void removePackedRef(String name) throws IOException {
packedRefs.remove(name);
writePackedRefs();
}
@@ -508,5 +512,4 @@ private static BufferedReader openReader(final File fileLocation)
return new BufferedReader(new InputStreamReader(new FileInputStream(
fileLocation), Constants.CHARSET));
}
-
}
--
1.6.1.rc4.301.g5497a
^ permalink raw reply related
* [JGIT PATCH 03/13] Cache an Inflater inside a WindowCursor and reuse it as much as possible
From: Shawn O. Pearce @ 2008-12-23 0:27 UTC (permalink / raw)
To: Robin Rosenberg; +Cc: git
In-Reply-To: <1229992043-1053-3-git-send-email-spearce@spearce.org>
By caching the Inflater within the WindowCursor we can improve
performance associated with reading objects from the pack files.
Each read can use the cached Inflater, especially when chasing
down a delta chain. This avoids locking on the global cache.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
.../jgit/lib/DeltaRefPackedObjectLoader.java | 2 +-
.../src/org/spearce/jgit/lib/PackFile.java | 7 +++-
.../src/org/spearce/jgit/lib/Repository.java | 7 +++-
.../src/org/spearce/jgit/lib/WindowCursor.java | 33 ++++++++++++++------
.../src/org/spearce/jgit/lib/WindowedFile.java | 10 +-----
.../src/org/spearce/jgit/revwalk/RevWalk.java | 4 +-
.../src/org/spearce/jgit/transport/IndexPack.java | 9 ++++-
7 files changed, 47 insertions(+), 25 deletions(-)
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/DeltaRefPackedObjectLoader.java b/org.spearce.jgit/src/org/spearce/jgit/lib/DeltaRefPackedObjectLoader.java
index 042d3a8..b126bbd 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/DeltaRefPackedObjectLoader.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/DeltaRefPackedObjectLoader.java
@@ -54,7 +54,7 @@ DeltaRefPackedObjectLoader(final WindowCursor curs, final PackFile pr,
}
protected PackedObjectLoader getBaseLoader() throws IOException {
- final PackedObjectLoader or = pack.get(deltaBase);
+ final PackedObjectLoader or = pack.get(curs, deltaBase);
if (or == null)
throw new MissingObjectException(deltaBase, "delta base");
return or;
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/PackFile.java b/org.spearce.jgit/src/org/spearce/jgit/lib/PackFile.java
index 8ebd440..6cd85b1 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/PackFile.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/PackFile.java
@@ -120,7 +120,12 @@ public boolean hasObject(final AnyObjectId id) {
* the pack file or the index could not be read.
*/
public PackedObjectLoader get(final AnyObjectId id) throws IOException {
- return get(new WindowCursor(), id);
+ final WindowCursor wc = new WindowCursor();
+ try {
+ return get(wc, id);
+ } finally {
+ wc.release();
+ }
}
/**
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
index a319c00..ff36a3d 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
@@ -251,7 +251,12 @@ public boolean hasObject(final AnyObjectId objectId) {
*/
public ObjectLoader openObject(final AnyObjectId id)
throws IOException {
- return openObject(new WindowCursor(),id);
+ final WindowCursor wc = new WindowCursor();
+ try {
+ return openObject(wc, id);
+ } finally {
+ wc.release();
+ }
}
/**
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCursor.java b/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCursor.java
index 0f4dab9..7aad081 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCursor.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCursor.java
@@ -46,6 +46,8 @@
/** Temporary buffer large enough for at least one raw object id. */
final byte[] tempId = new byte[Constants.OBJECT_ID_LENGTH];
+ private Inflater inf;
+
ByteWindow window;
Object handle;
@@ -98,16 +100,8 @@ int copy(final WindowedFile provider, long position, final byte[] dstbuf,
* data to.
* @param dstoff
* current offset within <code>dstbuf</code> to inflate into.
- * @param inf
- * the inflater to feed input to. The caller is responsible for
- * initializing the inflater as multiple windows may need to
- * supply data to the same inflater to completely decompress
- * something.
* @return updated <code>dstoff</code> based on the number of bytes
- * successfully copied into <code>dstbuf</code> by
- * <code>inf</code>. If the inflater is not yet finished then
- * another window's data must still be supplied as input to finish
- * decompression.
+ * successfully inflated into <code>dstbuf</code>.
* @throws IOException
* this cursor does not match the provider or id and the proper
* window could not be acquired through the provider's cache.
@@ -116,8 +110,12 @@ int copy(final WindowedFile provider, long position, final byte[] dstbuf,
* stream corruption is likely.
*/
int inflate(final WindowedFile provider, long position,
- final byte[] dstbuf, int dstoff, final Inflater inf)
+ final byte[] dstbuf, int dstoff)
throws IOException, DataFormatException {
+ if (inf == null)
+ inf = InflaterCache.get();
+ else
+ inf.reset();
for (;;) {
pin(provider, position);
dstoff = window.inflate(handle, position, dstbuf, dstoff, inf);
@@ -138,5 +136,20 @@ private void pin(final WindowedFile provider, final long position)
public void release() {
window = null;
handle = null;
+ try {
+ InflaterCache.release(inf);
+ } finally {
+ inf = null;
+ }
+ }
+
+ /**
+ * @param curs cursor to release; may be null.
+ * @return always null.
+ */
+ public static WindowCursor release(final WindowCursor curs) {
+ if (curs != null)
+ curs.release();
+ return null;
}
}
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/WindowedFile.java b/org.spearce.jgit/src/org/spearce/jgit/lib/WindowedFile.java
index f28524f..454f98b 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/WindowedFile.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/WindowedFile.java
@@ -45,7 +45,6 @@
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel.MapMode;
import java.util.zip.DataFormatException;
-import java.util.zip.Inflater;
/**
* Read-only cached file access.
@@ -240,13 +239,8 @@ public void copyToStream(long position, final byte[] buf, long cnt,
void readCompressed(final long position, final byte[] dstbuf,
final WindowCursor curs) throws IOException, DataFormatException {
- final Inflater inf = InflaterCache.get();
- try {
- if (curs.inflate(this, position, dstbuf, 0, inf) != dstbuf.length)
- throw new EOFException("Short compressed stream at " + position);
- } finally {
- InflaterCache.release(inf);
- }
+ if (curs.inflate(this, position, dstbuf, 0) != dstbuf.length)
+ throw new EOFException("Short compressed stream at " + position);
}
/**
diff --git a/org.spearce.jgit/src/org/spearce/jgit/revwalk/RevWalk.java b/org.spearce.jgit/src/org/spearce/jgit/revwalk/RevWalk.java
index d7e4c58..b1571ab 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/revwalk/RevWalk.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/revwalk/RevWalk.java
@@ -651,7 +651,7 @@ else if (!(c instanceof RevTree))
if ((t.flags & PARSED) != 0)
return t;
- final ObjectLoader ldr = db.openObject(t);
+ final ObjectLoader ldr = db.openObject(curs, t);
if (ldr == null)
throw new MissingObjectException(t, Constants.TYPE_TREE);
if (ldr.getType() != Constants.OBJ_TREE)
@@ -680,7 +680,7 @@ public RevObject parseAny(final AnyObjectId id)
throws MissingObjectException, IOException {
RevObject r = objects.get(id);
if (r == null) {
- final ObjectLoader ldr = db.openObject(id);
+ final ObjectLoader ldr = db.openObject(curs, id);
if (ldr == null)
throw new MissingObjectException(id.toObjectId(), "unknown");
final byte[] data = ldr.getCachedBytes();
diff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java b/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java
index 3e2187c..82cd615 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java
@@ -68,6 +68,7 @@
import org.spearce.jgit.lib.PackIndexWriter;
import org.spearce.jgit.lib.ProgressMonitor;
import org.spearce.jgit.lib.Repository;
+import org.spearce.jgit.lib.WindowCursor;
import org.spearce.jgit.util.NB;
/** Indexes Git pack files for local use. */
@@ -173,6 +174,8 @@ public static IndexPack create(final Repository db, final InputStream is)
/** If {@link #fixThin} this is the last byte of the original checksum. */
private long originalEOF;
+ private WindowCursor readCurs;
+
/**
* Create a new pack indexer utility.
*
@@ -189,6 +192,7 @@ public IndexPack(final Repository db, final InputStream src,
repo = db;
in = src;
inflater = InflaterCache.get();
+ readCurs = new WindowCursor();
buf = new byte[BUFFER_SIZE];
objectData = new byte[BUFFER_SIZE];
objectDigest = Constants.newMessageDigest();
@@ -325,6 +329,7 @@ public void index(final ProgressMonitor progress) throws IOException {
} finally {
inflater = null;
}
+ readCurs = WindowCursor.release(readCurs);
progress.endTask();
if (packOut != null)
@@ -461,7 +466,7 @@ private void fixThinPack(final ProgressMonitor progress) throws IOException {
final Deflater def = new Deflater(Deflater.DEFAULT_COMPRESSION, false);
long end = originalEOF;
for (final ObjectId baseId : new ArrayList<ObjectId>(baseById.keySet())) {
- final ObjectLoader ldr = repo.openObject(baseId);
+ final ObjectLoader ldr = repo.openObject(readCurs, baseId);
if (ldr == null)
continue;
final byte[] data = ldr.getBytes();
@@ -715,7 +720,7 @@ private void verifySafeObject(final AnyObjectId id, final int type,
}
}
- final ObjectLoader ldr = repo.openObject(id);
+ final ObjectLoader ldr = repo.openObject(readCurs, id);
if (ldr != null) {
final byte[] existingData = ldr.getCachedBytes();
if (ldr.getType() != type || !Arrays.equals(data, existingData)) {
--
1.6.1.rc4.301.g5497a
^ permalink raw reply related
* [JGIT PATCH 05/13] Make PackFile thread-safe
From: Shawn O. Pearce @ 2008-12-23 0:27 UTC (permalink / raw)
To: Robin Rosenberg; +Cc: git
In-Reply-To: <1229992043-1053-5-git-send-email-spearce@spearce.org>
We really should try to avoid allocating the reverse index within
the pack object itself, and instead make the applications that do
use this data manage it themselves. This way the index could be
released in memory when its no longer used, and the locking could
be bypassed entirely.
Since most of PackFile is dependent upon the WindowedFile we can
mostly ignore synchronization in this class.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
.../src/org/spearce/jgit/lib/PackFile.java | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/PackFile.java b/org.spearce.jgit/src/org/spearce/jgit/lib/PackFile.java
index 6cd85b1..ca5681b 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/PackFile.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/PackFile.java
@@ -341,7 +341,7 @@ private long findEndOffset(final long startOffset)
return getReverseIdx().findNextOffset(startOffset, maxOffset);
}
- private PackReverseIndex getReverseIdx() {
+ private synchronized PackReverseIndex getReverseIdx() {
if (reverseIdx == null)
reverseIdx = new PackReverseIndex(idx);
return reverseIdx;
--
1.6.1.rc4.301.g5497a
^ permalink raw reply related
* [JGIT PATCH 07/13] Don't open a PackFile multiple times on scanForPacks
From: Shawn O. Pearce @ 2008-12-23 0:27 UTC (permalink / raw)
To: Robin Rosenberg; +Cc: git
In-Reply-To: <1229992043-1053-7-git-send-email-spearce@spearce.org>
If we already have a given PackFile open in this repository then
we should reuse the existing PackFile handle.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
.../src/org/spearce/jgit/lib/PackFile.java | 5 +++++
.../src/org/spearce/jgit/lib/Repository.java | 8 +++++++-
.../src/org/spearce/jgit/lib/WindowedFile.java | 7 ++++++-
3 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/PackFile.java b/org.spearce.jgit/src/org/spearce/jgit/lib/PackFile.java
index ca5681b..fc1b6ea 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/PackFile.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/PackFile.java
@@ -94,6 +94,11 @@ final PackedObjectLoader resolveBase(final WindowCursor curs, final long ofs)
return reader(curs, ofs);
}
+ /** @return the File object which locates this pack on disk. */
+ public File getPackFile() {
+ return pack.getFile();
+ }
+
/**
* Determine if an object is contained within the pack file.
* <p>
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
index 89ad991..8f6e96e 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
@@ -825,6 +825,7 @@ synchronized (this) {
*/
public void scanForPacks() {
final ArrayList<PackFile> p = new ArrayList<PackFile>();
+ p.addAll(Arrays.asList(packs()));
for (final File d : objectsDirs())
scanForPacks(new File(d, "pack"), p);
final PackFile[] arr = new PackFile[p.size()];
@@ -843,7 +844,7 @@ public boolean accept(final File baseDir, final String n) {
}
});
if (idxList != null) {
- for (final String indexName : idxList) {
+ SCAN: for (final String indexName : idxList) {
final String n = indexName.substring(0, indexName.length() - 4);
final File idxFile = new File(packDir, n + ".idx");
final File packFile = new File(packDir, n + ".pack");
@@ -856,6 +857,11 @@ public boolean accept(final File baseDir, final String n) {
continue;
}
+ for (final PackFile p : packList) {
+ if (packFile.equals(p.getPackFile()))
+ continue SCAN;
+ }
+
try {
packList.add(new PackFile(this, idxFile, packFile));
} catch (IOException ioe) {
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/WindowedFile.java b/org.spearce.jgit/src/org/spearce/jgit/lib/WindowedFile.java
index 454f98b..f640c42 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/WindowedFile.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/WindowedFile.java
@@ -101,13 +101,18 @@ public long length() {
return length;
}
+ /** @return the absolute file object this file reads from. */
+ public File getFile() {
+ return fPath.getAbsoluteFile();
+ }
+
/**
* Get the path name of this file.
*
* @return the absolute path name of the file.
*/
public String getName() {
- return fPath.getAbsolutePath();
+ return getFile().getPath();
}
/**
--
1.6.1.rc4.301.g5497a
^ permalink raw reply related
* [JGIT PATCH 06/13] Make Repository thread-safe
From: Shawn O. Pearce @ 2008-12-23 0:27 UTC (permalink / raw)
To: Robin Rosenberg; +Cc: git
In-Reply-To: <1229992043-1053-6-git-send-email-spearce@spearce.org>
The Repository class itself is now thread-safe. Thread safety is
ensured by copying values onto the caller stack prior to use.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
.../src/org/spearce/jgit/lib/Repository.java | 75 ++++++++++++-------
1 files changed, 47 insertions(+), 28 deletions(-)
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
index ff36a3d..89ad991 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
@@ -46,6 +46,7 @@
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -79,20 +80,22 @@
* </ul>
* </li>
* </ul>
- *
+ * <p>
+ * This class is thread-safe.
+ * <p>
* This implementation only handles a subtly undocumented subset of git features.
*
*/
public class Repository {
private final File gitDir;
- private final File[] objectsDirs;
-
private final RepositoryConfig config;
private final RefDatabase refs;
- private PackFile[] packs;
+ private File[] objectDirectoryList;
+
+ private PackFile[] packFileList;
private GitIndex index;
@@ -111,18 +114,19 @@
public Repository(final File d) throws IOException {
gitDir = d.getAbsoluteFile();
try {
- objectsDirs = readObjectsDirs(FS.resolve(gitDir, "objects"),
- new ArrayList<File>()).toArray(new File[0]);
+ objectDirectoryList = readObjectsDirs(
+ FS.resolve(gitDir, "objects"), new ArrayList<File>())
+ .toArray(new File[0]);
} catch (IOException e) {
IOException ex = new IOException("Cannot find all object dirs for " + gitDir);
ex.initCause(e);
throw ex;
}
refs = new RefDatabase(this);
- packs = new PackFile[0];
+ packFileList = new PackFile[0];
config = new RepositoryConfig(this);
- final boolean isExisting = objectsDirs[0].exists();
+ final boolean isExisting = objectDirectoryList[0].exists();
if (isExisting) {
getConfig().load();
final String repositoryFormatVersion = getConfig().getString(
@@ -138,7 +142,8 @@ public Repository(final File d) throws IOException {
scanForPacks();
}
- private Collection<File> readObjectsDirs(File objectsDir, Collection<File> ret) throws IOException {
+ private static Collection<File> readObjectsDirs(File objectsDir,
+ Collection<File> ret) throws IOException {
ret.add(objectsDir);
final File altFile = FS.resolve(objectsDir, "info/alternates");
if (altFile.exists()) {
@@ -160,7 +165,7 @@ public Repository(final File d) throws IOException {
*
* @throws IOException
*/
- public void create() throws IOException {
+ public synchronized void create() throws IOException {
if (gitDir.exists()) {
throw new IllegalStateException("Repository already exists: "
+ gitDir);
@@ -169,9 +174,9 @@ public void create() throws IOException {
gitDir.mkdirs();
refs.create();
- objectsDirs[0].mkdirs();
- new File(objectsDirs[0], "pack").mkdir();
- new File(objectsDirs[0], "info").mkdir();
+ objectDirectoryList[0].mkdirs();
+ new File(objectDirectoryList[0], "pack").mkdir();
+ new File(objectDirectoryList[0], "info").mkdir();
new File(gitDir, "branches").mkdir();
new File(gitDir, "remotes").mkdir();
@@ -182,6 +187,14 @@ public void create() throws IOException {
getConfig().save();
}
+ private synchronized File[] objectsDirs(){
+ return objectDirectoryList;
+ }
+
+ private synchronized PackFile[] packs(){
+ return packFileList;
+ }
+
/**
* @return GIT_DIR
*/
@@ -193,7 +206,7 @@ public File getDirectory() {
* @return the directory containing the objects owned by this repository.
*/
public File getObjectsDirectory() {
- return objectsDirs[0];
+ return objectsDirs()[0];
}
/**
@@ -217,6 +230,7 @@ public File toFile(final AnyObjectId objectId) {
final String n = objectId.name();
String d=n.substring(0, 2);
String f=n.substring(2);
+ final File[] objectsDirs = objectsDirs();
for (int i=0; i<objectsDirs.length; ++i) {
File ret = new File(new File(objectsDirs[i], d), f);
if (ret.exists())
@@ -231,6 +245,7 @@ public File toFile(final AnyObjectId objectId) {
* known shared repositories.
*/
public boolean hasObject(final AnyObjectId objectId) {
+ final PackFile[] packs = packs();
int k = packs.length;
if (k > 0) {
do {
@@ -271,6 +286,7 @@ public ObjectLoader openObject(final AnyObjectId id)
*/
public ObjectLoader openObject(final WindowCursor curs, final AnyObjectId id)
throws IOException {
+ final PackFile[] packs = packs();
int k = packs.length;
if (k > 0) {
do {
@@ -341,7 +357,7 @@ public ObjectLoader openObject(final WindowCursor curs, final AnyObjectId id)
void openObjectInAllPacks(final AnyObjectId objectId,
final Collection<PackedObjectLoader> resultLoaders,
final WindowCursor curs) throws IOException {
- for (PackFile pack : packs) {
+ for (PackFile pack : packs()) {
final PackedObjectLoader loader = pack.get(curs, objectId);
if (loader != null)
resultLoaders.add(loader);
@@ -766,11 +782,10 @@ public void close() {
closePacks();
}
- void closePacks() {
- for (int k = packs.length - 1; k >= 0; k--) {
- packs[k].close();
- }
- packs = new PackFile[0];
+ synchronized void closePacks() {
+ for (int k = packFileList.length - 1; k >= 0; k--)
+ packFileList[k].close();
+ packFileList = new PackFile[0];
}
/**
@@ -795,11 +810,13 @@ public void openPack(final File pack, final File idx) throws IOException {
throw new IllegalArgumentException("Pack " + pack
+ "does not match index " + idx);
- final PackFile[] cur = packs;
- final PackFile[] arr = new PackFile[cur.length + 1];
- System.arraycopy(cur, 0, arr, 1, cur.length);
- arr[0] = new PackFile(this, idx, pack);
- packs = arr;
+ synchronized (this) {
+ final PackFile[] cur = packFileList;
+ final PackFile[] arr = new PackFile[cur.length + 1];
+ System.arraycopy(cur, 0, arr, 1, cur.length);
+ arr[0] = new PackFile(this, idx, pack);
+ packFileList = arr;
+ }
}
/**
@@ -808,11 +825,13 @@ public void openPack(final File pack, final File idx) throws IOException {
*/
public void scanForPacks() {
final ArrayList<PackFile> p = new ArrayList<PackFile>();
- for (int i=0; i<objectsDirs.length; ++i)
- scanForPacks(new File(objectsDirs[i], "pack"), p);
+ for (final File d : objectsDirs())
+ scanForPacks(new File(d, "pack"), p);
final PackFile[] arr = new PackFile[p.size()];
p.toArray(arr);
- packs = arr;
+ synchronized (this) {
+ packFileList = arr;
+ }
}
private void scanForPacks(final File packDir, Collection<PackFile> packList) {
--
1.6.1.rc4.301.g5497a
^ permalink raw reply related
* [JGIT PATCH 09/13] Add AnyObjectId.copyTo(StringBuilder)
From: Shawn O. Pearce @ 2008-12-23 0:27 UTC (permalink / raw)
To: Robin Rosenberg; +Cc: git
In-Reply-To: <1229992043-1053-9-git-send-email-spearce@spearce.org>
This makes it easier to append an ObjectId onto a StringBuilder.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
.../src/org/spearce/jgit/lib/AnyObjectId.java | 17 ++++++++++++++++-
1 files changed, 16 insertions(+), 1 deletions(-)
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/AnyObjectId.java b/org.spearce.jgit/src/org/spearce/jgit/lib/AnyObjectId.java
index 943d916..3ec00ea 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/AnyObjectId.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/AnyObjectId.java
@@ -387,7 +387,22 @@ public void copyTo(final Writer w) throws IOException {
*/
public void copyTo(final char[] tmp, final Writer w) throws IOException {
toHexCharArray(tmp);
- w.write(tmp);
+ w.write(tmp, 0, STR_LEN);
+ }
+
+ /**
+ * Copy this ObjectId to a StringBuilder in hex format.
+ *
+ * @param tmp
+ * temporary char array to buffer construct into before writing.
+ * Must be at least large enough to hold 2 digits for each byte
+ * of object id (40 characters or larger).
+ * @param w
+ * the string to append onto.
+ */
+ public void copyTo(final char[] tmp, final StringBuilder w) {
+ toHexCharArray(tmp);
+ w.append(tmp, 0, STR_LEN);
}
private char[] toHexCharArray() {
--
1.6.1.rc4.301.g5497a
^ permalink raw reply related
* [JGIT PATCH 08/13] Expose RepositoryConfig.getBoolean so applications can use it
From: Shawn O. Pearce @ 2008-12-23 0:27 UTC (permalink / raw)
To: Robin Rosenberg; +Cc: git
In-Reply-To: <1229992043-1053-8-git-send-email-spearce@spearce.org>
There's no reason for these to be hidden from application level code.
We expose getInt because it is a popular type; getBoolean should also
be exposed because it is also a popular type.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
.../src/org/spearce/jgit/lib/RepositoryConfig.java | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java
index 3291bba..7df90cd 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java
@@ -210,7 +210,7 @@ public int getInt(final String section, String subsection,
* @return true if any value or defaultValue is true, false for missing or
* explicit false
*/
- protected boolean getBoolean(final String section, final String name,
+ public boolean getBoolean(final String section, final String name,
final boolean defaultValue) {
return getBoolean(section, null, name, defaultValue);
}
@@ -229,7 +229,7 @@ protected boolean getBoolean(final String section, final String name,
* @return true if any value or defaultValue is true, false for missing or
* explicit false
*/
- protected boolean getBoolean(final String section, String subsection,
+ public boolean getBoolean(final String section, String subsection,
final String name, final boolean defaultValue) {
String n = getRawString(section, subsection, name);
if (n == null)
--
1.6.1.rc4.301.g5497a
^ permalink raw reply related
* [JGIT PATCH 10/13] Add compare-and-swap semantics to RefUpdate
From: Shawn O. Pearce @ 2008-12-23 0:27 UTC (permalink / raw)
To: Robin Rosenberg; +Cc: git
In-Reply-To: <1229992043-1053-10-git-send-email-spearce@spearce.org>
This permits the caller to set the value it expects to find in the
Ref upon obtaining the update lock. If the ref value doesn't match
then the update is aborted with Result.LOCK_FAILURE, so the caller
can recover gracefully without making unexpected changes.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
.../src/org/spearce/jgit/lib/RefUpdate.java | 30 ++++++++++++++++++++
1 files changed, 30 insertions(+), 0 deletions(-)
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java
index 235c2fd..0c9ce91 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java
@@ -149,6 +149,9 @@
/** Old value of the ref, obtained after we lock it. */
private ObjectId oldValue;
+ /** If non-null, the value {@link #oldValue} must have to continue. */
+ private ObjectId expValue;
+
/** Result of the update operation. */
private Result result = Result.NOT_ATTEMPTED;
@@ -190,6 +193,27 @@ public void setNewObjectId(final AnyObjectId id) {
}
/**
+ * @return the expected value of the ref after the lock is taken, but before
+ * update occurs. Null to avoid the compare and swap test. Use
+ * {@link ObjectId#zeroId()} to indicate expectation of a
+ * non-existant ref.
+ */
+ public ObjectId getExpectedOldObjectId() {
+ return expValue;
+ }
+
+ /**
+ * @param id
+ * the expected value of the ref after the lock is taken, but
+ * before update occurs. Null to avoid the compare and swap test.
+ * Use {@link ObjectId#zeroId()} to indicate expectation of a
+ * non-existant ref.
+ */
+ public void setExpectedOldObjectId(final AnyObjectId id) {
+ expValue = id != null ? id.toObjectId() : null;
+ }
+
+ /**
* Check if this update wants to forcefully change the ref.
*
* @return true if this update should ignore merge tests.
@@ -370,6 +394,12 @@ private Result updateImpl(final RevWalk walk, final Store store)
return Result.LOCK_FAILURE;
try {
oldValue = db.idOf(getName());
+ if (expValue != null) {
+ final ObjectId o;
+ o = oldValue != null ? oldValue : ObjectId.zeroId();
+ if (!expValue.equals(o))
+ return Result.LOCK_FAILURE;
+ }
if (oldValue == null)
return store.store(lock, Result.NEW);
--
1.6.1.rc4.301.g5497a
^ permalink raw reply related
* [JGIT PATCH 11/13] Allow null new ObjectId during RefUpdate.delete
From: Shawn O. Pearce @ 2008-12-23 0:27 UTC (permalink / raw)
To: Robin Rosenberg; +Cc: git
In-Reply-To: <1229992043-1053-11-git-send-email-spearce@spearce.org>
If we are deleting a ref we really don't care about what the
new ObjectId value should be; it just doesn't matter. If we
didn't set the value we should consider it the same as if we
had a MissingObjectException, which means treat the value as
null and perform a force update test.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
.../src/org/spearce/jgit/lib/RefUpdate.java | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java
index 0c9ce91..1417f2c 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java
@@ -424,7 +424,7 @@ private Result updateImpl(final RevWalk walk, final Store store)
private static RevObject safeParse(final RevWalk rw, final AnyObjectId id)
throws IOException {
try {
- return rw.parseAny(id);
+ return id != null ? rw.parseAny(id) : null;
} catch (MissingObjectException e) {
// We can expect some objects to be missing, like if we are
// trying to force a deletion of a branch and the object it
--
1.6.1.rc4.301.g5497a
^ 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