* Re: [JGIT] Request for help
From: Jonas Fonseca @ 2009-09-03 15:38 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: Johannes Schindelin, Nasser Grainawi, Git Mailing List
In-Reply-To: <20090903144227.GH1033@spearce.org>
On Thu, Sep 3, 2009 at 10:42, Shawn O. Pearce<spearce@spearce.org> wrote:
> Jonas Fonseca <jonas.fonseca@gmail.com> wrote:
>> BTW, what is your opinion of making it a bit easier to import and use
>> the Maven configuration by putting a pom.xml in the top-level
>> directory? The actual pom.xml file responsible for building the jgit
>> library can still live on in jgit-maven/ if that is preferable.
>>
>> I am also thinking about "mavenizing" the .pgm subproject to make it
>> easier to browse and search the code from within NetBeans.
>
> Actually, now that we have forked out of the egit.git repository,
> I want to refactor the layout of the JGit project to be more maven
> like, and have a proper top-level pom to build things.
What kind of module structure do you have in mind? Do you want to move
some of the modules/subdirectories?
Some refactoring of the maven setup for JGit back was done back in
April in sonatype's (a maven company) JGit clone. It is not
signed-off, but can serve as a reference.
- http://github.com/sonatype/JGit/commit/641ae523c496f381a7673f4acfa0acdff9d3913e
The Maven layout in the sonatype clone simply uses the Eclipse project layout.
pom.xml: JGit :: Parent
|- org.spearce.jgit/pom.xml: JGit :: Core
|- org.spearce.jgit.pgm/pom.xml: JGit :: Programs
`- org.spearce.jgit.test/pom.xml: JGit :: Test
However, having tests in a separate module can be both good/bad. For
example, they will not automatically get run when you only build the
Core module.
Anyway, I would like to help.
--
Jonas Fonseca
^ permalink raw reply
* Re: [JGIT] Request for help
From: Shawn O. Pearce @ 2009-09-03 14:42 UTC (permalink / raw)
To: Jonas Fonseca; +Cc: Johannes Schindelin, Nasser Grainawi, Git Mailing List
In-Reply-To: <2c6b72b30909030545y4465b5c8j4b2b5587a07762c0@mail.gmail.com>
Jonas Fonseca <jonas.fonseca@gmail.com> wrote:
> BTW, what is your opinion of making it a bit easier to import and use
> the Maven configuration by putting a pom.xml in the top-level
> directory? The actual pom.xml file responsible for building the jgit
> library can still live on in jgit-maven/ if that is preferable.
>
> I am also thinking about "mavenizing" the .pgm subproject to make it
> easier to browse and search the code from within NetBeans.
Actually, now that we have forked out of the egit.git repository,
I want to refactor the layout of the JGit project to be more maven
like, and have a proper top-level pom to build things.
Unfortunately it seems that nobody can program a proper Maven pom
for a multi-project project unless they are one of the authors
of Maven itself. I watched the Apache MINA team struggle with it
until the Maven guys wanted to use their code, and fixed their build.
So, this refactoring is waiting for a Maven guru to contribute
an improvement. Unfortunately they are all busy...
So, to answer your original question, yes, we should make this
better, and patches are welcome. My own Maven-fu is just not up
to the task.
--
Shawn.
^ permalink raw reply
* Re: git-svn-Cloning repository with complicate nesting
From: Marc Branchaud @ 2009-09-03 14:31 UTC (permalink / raw)
To: Daniele Segato; +Cc: Git Mailing List
In-Reply-To: <9accb4400908270132vaccc4eegb58e2f0ee8de0797@mail.gmail.com>
Hi Daniele,
I think you're stuck. Someone who knows git-svn better than I might be able to figure out a solution (I haven't played with using wildcards in the middle of branches refspecs), but as far as I can tell git-svn can't support your repository's structure.
The fundamental problem is that the BRANCHES/ hierarchy isn't consistent. git-svn expects the directories under a 'branches' path to be branch names. In your case, you can't specify a configuration that covers your whole repository.
This:
branches = <url>/BRANCHES/DEV/*:refs/remotes/svn/dev/*
branches = <url>/BRANCHES/BUILDS/*:refs/remotes/svn/builds/*
will let you track the stuff under BRANCHES/DEV and BRANCHES/BUILDS, but won't let you see the V*.* branches.
This:
branches = <url>/BRANCHES/*:refs/remotes/svn/*
will let you see the V*.* branches, but will get confused over the DEV and BUILDS stuff (because it's expecting the layout to be DEV/root and BUILDS/root).
So I think git-svn would need to be modified to support your situation.
One possible approach is to make git-svn smart about what it considers a branch's name. In theory, what you'd like is to just specify
branches = <url>/BRANCHES/*:refs/remotes/svn/*
and have git-svn properly identify all the branches:
V1.0
V1.1
V1.2
DEV/FEATURE1
DEV/FEATURE2
DEV/FEATURE3
BUILDS/BUILD1
BUILDS/BUILD2
BUILDS/BUILD3
To do this, git-svn could track the current 'trunk' directory structure (just the top-level contents of the root should suffice). Then when it detects a new path under BRANCHES it could search through that path until it finds the same 'trunk' directory structure, and then use the path as the full branch name.
For example, say a repository's trunk has 3 directories and a file:
trunk/
foo/...
bar/...
baz/...
readme.txt
When a commit creates a new branch:
branches/some/path/
foo/...
bar/...
baz/...
readme.txt
git-svn sees that the commit is to a new path under branches/ and looks through branches/some/ and branches/some/path/ to find the trunk's contents, deciding in this case that 'some/path' is the branch's name.
Anyway, this is just an idea of how things might work. There are probably some corner-cases that could make this a bit tricky to implement...
M.
Daniele Segato wrote:
> Hi, this is my first message in the list: this may be a newbie
> question and my English may not be very good.
>
> I've an SVN repository structured like this:
>
> http://<url>/path/to/repo
> |
> HEAD
> |----- root
> |
> BRANCHES
> |----- V1.0
> | |----- root
> |
> |----- V1.1
> | |----- root
> |
> |----- V1.2
> | |----- root
> |
> |----- DEV
> | |----- FEATURE1
> | | |----- root
> | |
> | |----- FEATURE2
> | | |----- root
> | |
> | |----- FEATURE3
> | |----- root
> |
> |----- BUILDS
> |----- BUILD1
> | |----- root
> |
> |----- BUILD2
> | |----- root
> |
> |----- BUILD3
> |----- root
>
> the same for TAGS.
>
> I did this:
>
> git init
> git svn init <url>
> vim .git/config
>
> [core]
> repositoryformatversion = 0
> filemode = true
> bare = false
> logallrefupdates = true
> [svn-remote "svn"]
> url = <url>
> fetch = <url>/HEAD/root:refs/remotes/trunk
> branches = <url>/BRANCHES/*/root:refs/remotes/branches/*
> branches = <url>/BRANCHES/*/*/root:refs/remotes/devel/*
> tags = <url>/TAGS/*/root:refs/remotes/tags/*
>
>
> git svn fetch
>
>
> It is now cloning the repo (it is a really big repo)
>
>
> It is my configuration ok for the repository structure?
>
> if from another terminal I execute "git branch -r" I get:
> tags/V1.3.0
> tags/V1.3.0@3260
> tags/V1.3.1
> tags/V1.3.1@3359
> tags/V1.3.2
> tags/V1.3.2@4256
> tags/V1.4.0-COMMUNITY-FINAL
> tags/V1.4.0-ENTERPRISE-BETA@4241
> trunk
> trunk@4475
>
> It should have already created some branch but I don't see any...
>
> what are those @XXXX number for some of those branches?
>
> Is the syntax of the svn-remote configuration correct?
>
> with this:
> branches = <url>/BRANCHES/*/*/root:refs/remotes/devel/*
> how does git choose the name of the branch? (
> refs/remotes/devel/WHAT_GOES_HERE ? )
>
> I would like it to use the tuple */* of the directory
>
>
> If the syntax of my configuration is not correct, where can I found a
> documentation about it? I couldn't find one.
>
>
> Thanks
> Regards,
> Daniele
> --
> 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
^ permalink raw reply
* Re: [JGIT] Request for help
From: Jonas Fonseca @ 2009-09-03 12:45 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: Johannes Schindelin, Nasser Grainawi, Git Mailing List
In-Reply-To: <20090903012207.GF1033@spearce.org>
On Wed, Sep 2, 2009 at 21:22, Shawn O. Pearce<spearce@spearce.org> wrote:
> Yea, for the most part I think we use Eclipse, and you just have
> to import JGit's top level directory into Eclipse as it comes with
> Eclipse project files. But I know some folks only use our Maven
> build (under jgit-maven/jgit) or use NetBeans. I have no idea how
> to import the project into the latter or configure its unit tests
> to run.
NetBeans comes with very good support for Maven projects. Importing
JGit into NetBeans is just a matter of using the "Open Project" wizard
and locating jgit-maven/jgit. This will also configure the unit tests
to run.
BTW, what is your opinion of making it a bit easier to import and use
the Maven configuration by putting a pom.xml in the top-level
directory? The actual pom.xml file responsible for building the jgit
library can still live on in jgit-maven/ if that is preferable.
I am also thinking about "mavenizing" the .pgm subproject to make it
easier to browse and search the code from within NetBeans.
--
Jonas Fonseca
^ permalink raw reply
* [PATCH v4] Add script for importing bits-and-pieces to Git.
From: Peter Krefting @ 2009-09-03 12:15 UTC (permalink / raw)
To: git
Allows the user to import version history that is stored in bits and
pieces in the file system, for instance snapshots of old development
trees, or day-by-day backups. A configuration file is used to
describe the relationship between the different files and allow
describing branches and merges, as well as authorship and commit
messages.
Output is created in a format compatible with git-fast-import.
Full documentation is provided inline in perldoc format.
Signed-off-by: Peter Krefting <peter@softwolves.pp.se>
---
This version improves the configuration file parser to allow quoted
strings.
contrib/fast-import/import-directories.perl | 416 +++++++++++++++++++++++++++
1 files changed, 416 insertions(+), 0 deletions(-)
create mode 100755 contrib/fast-import/import-directories.perl
diff --git a/contrib/fast-import/import-directories.perl b/contrib/fast-import/import-directories.perl
new file mode 100755
index 0000000..5782d80
--- /dev/null
+++ b/contrib/fast-import/import-directories.perl
@@ -0,0 +1,416 @@
+#!/usr/bin/perl -w
+#
+# Copyright 2008-2009 Peter Krefting <peter@softwolves.pp.se>
+#
+# ------------------------------------------------------------------------
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# ------------------------------------------------------------------------
+
+=pod
+
+=head1 NAME
+
+import-directories - Import bits and pieces to Git.
+
+=head1 SYNOPSIS
+
+B<import-directories.perl> F<configfile> F<outputfile>
+
+=head1 DESCRIPTION
+
+Script to import arbitrary projects version controlled by the "copy the
+source directory to a new location and edit it there"-version controlled
+projects into version control. Handles projects with arbitrary branching
+and version trees, taking a file describing the inputs and generating a
+file compatible with the L<git-fast-import(1)> format.
+
+=head1 CONFIGURATION FILE
+
+=head2 Format
+
+The configuration file is based on the standard I<.ini> format.
+
+ ; Comments start with semi-colons
+ [section]
+ key=value
+
+Please see below for information on how to escape special characters.
+
+=head2 Global configuration
+
+Global configuration is done in the B<[config]> section, which should be
+the first section in the file. Configuration can be changed by
+repeating configuration sections later on.
+
+ [config]
+ ; configure conversion of CRLFs. "convert" means that all CRLFs
+ ; should be converted into LFs (suitable for the core.autocrlf
+ ; setting set to true in Git). "none" means that all data is
+ ; treated as binary.
+ crlf=convert
+
+=head2 Revision configuration
+
+Each revision that is to be imported is described in three
+sections. Revisions should be defined in topological order, so
+that a revision's parent has always been defined when a new revision
+is introduced. All the sections for one revision must be defined
+before defining the next revision.
+
+Each revision is assigned a unique numerical identifier. The
+numbers do not need to be consecutive, nor monotonically
+increasing.
+
+For instance, if your configuration file contains only the two
+revisions 4711 and 42, where 4711 is the initial commit, the
+only requirement is that 4711 is completely defined before 42.
+
+=pod
+
+=head3 Revision description section
+
+A section whose section name is just an integer gives meta-data
+about the revision.
+
+ [3]
+ ; author sets the author of the revisions
+ author=Peter Krefting <peter@softwolves.pp.se>
+ ; branch sets the branch that the revision should be committed to
+ branch=master
+ ; parent describes the revision that is the parent of this commit
+ ; (optional)
+ parent=1
+ ; merges describes a revision that is merged into this commit
+ ; (optional; can be repeated)
+ merges=2
+ ; selects one file to take the timestamp from
+ ; (optional; if unspecified, the most recent file from the .files
+ ; section is used)
+ timestamp=3/source.c
+
+=head3 Revision contents section
+
+A section whose section name is an integer followed by B<.files>
+describe all the files included in this revision. If a file that
+was available previously is not included in this revision, it will
+be removed.
+
+If an on-disk revision is incomplete, you can point to files from
+a previous revision. There are no restriction as to where the source
+files are located, nor to the names of them.
+
+ [3.files]
+ ; the key is the path inside the repository, the value is the path
+ ; as seen from the importer script.
+ source.c=ver-3.00/source.c
+ source.h=ver-2.99/source.h
+ readme.txt=ver-3.00/introduction to the project.txt
+
+File names are treated as byte strings (but please see below on
+quoting rules), and should be stored in the configuration file in
+the encoding that should be used in the generated repository.
+
+=head3 Revision commit message section
+
+A section whose section name is an integer followed by B<.message>
+gives the commit message. This section is read verbatim, up until
+the beginning of the next section. As such, a commit message may not
+contain a line that begins with an opening square bracket ("[") and
+ends with a closing square bracket ("]"), unless they are surrounded
+by whitespace or other characters.
+
+ [3.message]
+ Implement foobar.
+ ; trailing blank lines are ignored.
+
+=cut
+
+# Globals
+use strict;
+use integer;
+my $crlfmode = 0;
+my @revs;
+my (%revmap, %message, %files, %author, %branch, %parent, %merges, %time, %timesource);
+my $sectiontype = 0;
+my $rev = 0;
+my $mark = 1;
+
+# Check command line
+if ($#ARGV < 1 || $ARGV[0] =~ /^--?h/)
+{
+ exec('perldoc', $0);
+ exit 1;
+}
+
+# Open configuration
+my $config = $ARGV[0];
+open CFG, '<', $config or die "Cannot open configuration file \"$config\": ";
+
+# Open output
+my $output = $ARGV[1];
+open OUT, '>', $output or die "Cannot create output file \"$output\": ";
+binmode OUT;
+
+LINE: while (my $line = <CFG>)
+{
+ $line =~ s/\r?\n$//;
+ next LINE if $sectiontype != 4 && $line eq '';
+ next LINE if $line =~ /^;/;
+ my $oldsectiontype = $sectiontype;
+ my $oldrev = $rev;
+
+ # Sections
+ if ($line =~ m"^\[(config|(\d+)(|\.files|\.message))\]$")
+ {
+ if ($1 eq 'config')
+ {
+ $sectiontype = 1;
+ }
+ elsif ($3 eq '')
+ {
+ $sectiontype = 2;
+ $rev = $2;
+ # Create a new revision
+ die "Duplicate rev: $line\n " if defined $revmap{$rev};
+ print "Reading revision $rev\n";
+ push @revs, $rev;
+ $revmap{$rev} = $mark ++;
+ $time{$revmap{$rev}} = 0;
+ }
+ elsif ($3 eq '.files')
+ {
+ $sectiontype = 3;
+ $rev = $2;
+ die "Revision mismatch: $line\n " unless $rev == $oldrev;
+ }
+ elsif ($3 eq '.message')
+ {
+ $sectiontype = 4;
+ $rev = $2;
+ die "Revision mismatch: $line\n " unless $rev == $oldrev;
+ }
+ else
+ {
+ die "Internal parse error: $line\n ";
+ }
+ next LINE;
+ }
+
+ # Parse data
+ if ($sectiontype != 4)
+ {
+ # Key and value
+ if ($line =~ m"^\s*([^\s].*=.*[^\s])\s*$")
+ {
+ my ($key, $value) = &parsekeyvaluepair($1);
+ # Global configuration
+ if (1 == $sectiontype)
+ {
+ if ($key eq 'crlf')
+ {
+ $crlfmode = 1, next LINE if $value eq 'convert';
+ $crlfmode = 0, next LINE if $value eq 'none';
+ }
+ die "Unknown configuration option: $line\n ";
+ }
+ # Revision specification
+ if (2 == $sectiontype)
+ {
+ my $current = $revmap{$rev};
+ $author{$current} = $value, next LINE if $key eq 'author';
+ $branch{$current} = $value, next LINE if $key eq 'branch';
+ $parent{$current} = $value, next LINE if $key eq 'parent';
+ $timesource{$current} = $value, next LINE if $key eq 'timestamp';
+ push(@{$merges{$current}}, $value), next LINE if $key eq 'merges';
+ die "Unknown revision option: $line\n ";
+ }
+ # Filespecs
+ if (3 == $sectiontype)
+ {
+ # Add the file and create a marker
+ die "File not found: $line\n " unless -f $value;
+ my $current = $revmap{$rev};
+ ${$files{$current}}{$key} = $mark;
+ my $time = &fileblob($value, $crlfmode, $mark ++);
+
+ # Update revision timestamp if more recent than other
+ # files seen, or if this is the file we have selected
+ # to take the time stamp from using the "timestamp"
+ # directive.
+ if ((defined $timesource{$current} && $timesource{$current} eq $value)
+ || $time > $time{$current})
+ {
+ $time{$current} = $time;
+ }
+ }
+ }
+ else
+ {
+ die "Parse error: $line\n ";
+ }
+ }
+ else
+ {
+ # Commit message
+ my $current = $revmap{$rev};
+ if (defined $message{$current})
+ {
+ $message{$current} .= "\n";
+ }
+ $message{$current} .= $line;
+ }
+}
+close CFG;
+
+# Start spewing out data for git-fast-import
+foreach my $commit (@revs)
+{
+ # Progress
+ print OUT "progress Creating revision $commit\n";
+
+ # Create commit header
+ my $mark = $revmap{$commit};
+
+ # Branch and commit id
+ print OUT "commit refs/heads/", $branch{$mark}, "\nmark :", $mark, "\n";
+
+ # Author and timestamp
+ die "No timestamp defined for $commit (no files?)\n" unless defined $time{$mark};
+ print OUT "committer ", $author{$mark}, " ", $time{$mark}, " +0100\n";
+
+ # Commit message
+ die "No message defined for $commit\n" unless defined $message{$mark};
+ my $message = $message{$mark};
+ $message =~ s/\n$//; # Kill trailing empty line
+ print OUT "data ", length($message), "\n", $message, "\n";
+
+ # Parent and any merges
+ print OUT "from :", $revmap{$parent{$mark}}, "\n" if defined $parent{$mark};
+ if (defined $merges{$mark})
+ {
+ foreach my $merge (@{$merges{$mark}})
+ {
+ print OUT "merge :", $revmap{$merge}, "\n";
+ }
+ }
+
+ # Output file marks
+ print OUT "deleteall\n"; # start from scratch
+ foreach my $file (sort keys %{$files{$mark}})
+ {
+ print OUT "M 644 :", ${$files{$mark}}{$file}, " $file\n";
+ }
+ print OUT "\n";
+}
+
+# Create one file blob
+sub fileblob
+{
+ my ($filename, $crlfmode, $mark) = @_;
+
+ # Import the file
+ print OUT "progress Importing $filename\nblob\nmark :$mark\n";
+ open FILE, '<', $filename or die "Cannot read $filename\n ";
+ binmode FILE;
+ my ($size, $mtime) = (stat(FILE))[7,9];
+ my $file;
+ read FILE, $file, $size;
+ close FILE;
+ $file =~ s/\r\n/\n/g if $crlfmode;
+ print OUT "data ", length($file), "\n", $file, "\n";
+
+ return $mtime;
+}
+
+# Parse a key=value pair
+sub parsekeyvaluepair
+{
+=pod
+
+=head2 Escaping special characters
+
+Key and value strings may be enclosed in quotes, in which case
+whitespace inside the quotes is preserved. Additionally, an equal
+sign may be included in the key by preceeding it with a backslash.
+For example:
+
+ "key1 "=value1
+ key2=" value2"
+ key\=3=value3
+ key4=value=4
+ "key5""=value5
+
+Here the first key is "key1 " (note the trailing white-space) and the
+second value is " value2" (note the leading white-space). The third
+key contains an equal sign "key=3" and so does the fourth value, which
+does not need to be escaped. The fifth key contains a trailing quote,
+which does not need to be escaped since it is inside a surrounding
+quote.
+
+=cut
+ my $pair = shift;
+
+ # Separate key and value by the first non-quoted equal sign
+ my ($key, $value);
+ if ($pair =~ /^(.*[^\\])=(.*)$/)
+ {
+ ($key, $value) = ($1, $2)
+ }
+ else
+ {
+ die "Parse error: $pair\n ";
+ }
+
+ # Unquote and unescape the key and value separately
+ return (&unescape($key), &unescape($value));
+}
+
+# Unquote and unescape
+sub unescape
+{
+ my $string = shift;
+
+ # First remove enclosing quotes. Backslash before the trailing
+ # quote leaves both.
+ if ($string =~ /^"(.*[^\\])"$/)
+ {
+ $string = $1;
+ }
+
+ # Second remove any backslashes inside the unquoted string.
+ # For later: Handle special sequences like \t ?
+ $string =~ s/\\(.)/$1/g;
+
+ return $string;
+}
+
+__END__
+
+=pod
+
+=head1 EXAMPLES
+
+B<import-directories.perl> F<project.import>
+
+=head1 AUTHOR
+
+Copyright 2008-2009 Peter Krefting E<lt>peter@softwolves.pp.se>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation.
+
+=cut
--
1.6.3.3
^ permalink raw reply related
* [PATCH v5] import-tars: Allow per-tar author and commit message.
From: Peter Krefting @ 2009-09-03 12:15 UTC (permalink / raw)
To: git
If the "--metainfo=<ext>" option is given on the command line, a file
called "<filename.tar>.<ext>" will be used to create the commit message
for "<filename.tar>", instead of using "Imported from filename.tar".
The author and committer of the tar ball can also be overridden by
embedding an "Author:" or "Committer:" header in the metainfo file.
Signed-off-by: Peter Krefting <peter@softwolves.pp.se>
---
Fixed script to allow an empty line to stop parsing message for
header lines, and fixed indentation style to match the rest of the
script.
contrib/fast-import/import-tars.perl | 50 +++++++++++++++++++++++++++++++---
1 files changed, 46 insertions(+), 4 deletions(-)
diff --git a/contrib/fast-import/import-tars.perl b/contrib/fast-import/import-tars.perl
index 78e40d2..a909716 100755
--- a/contrib/fast-import/import-tars.perl
+++ b/contrib/fast-import/import-tars.perl
@@ -8,9 +8,20 @@
## perl import-tars.perl *.tar.bz2
## git whatchanged import-tars
##
+## Use --metainfo to specify the extension for a meta data file, where
+## import-tars can read the commit message and optionally author and
+## committer information.
+##
+## echo 'This is the commit message' > myfile.tar.bz2.msg
+## perl import-tars.perl --metainfo=msg myfile.tar.bz2
use strict;
-die "usage: import-tars *.tar.{gz,bz2,Z}\n" unless @ARGV;
+use Getopt::Long;
+
+my $metaext = '';
+
+die "usage: import-tars [--metainfo=extension] *.tar.{gz,bz2,Z}\n"
+ unless GetOptions('metainfo=s' => \$metaext) && @ARGV;
my $branch_name = 'import-tars';
my $branch_ref = "refs/heads/$branch_name";
@@ -109,12 +120,43 @@ foreach my $tar_file (@ARGV)
$have_top_dir = 0 if $top_dir ne $1;
}
+ my $commit_msg = "Imported from $tar_file.";
+ my $this_committer_name = $committer_name;
+ my $this_committer_email = $committer_email;
+ my $this_author_name = $author_name;
+ my $this_author_email = $author_email;
+ if ($metaext ne '') {
+ # Optionally read a commit message from <filename.tar>.msg
+ # Add a line on the form "Committer: name <e-mail>" to override
+ # the committer and "Author: name <e-mail>" to override the
+ # author for this tar ball.
+ if (open MSG, '<', "${tar_file}.${metaext}") {
+ my $header_done = 0;
+ $commit_msg = '';
+ while (<MSG>) {
+ if (!$header_done && /^Committer:\s+([^<>]*)\s+<(.*)>\s*$/i) {
+ $this_committer_name = $1;
+ $this_committer_email = $2;
+ } elsif (!$header_done && /^Author:\s+([^<>]*)\s+<(.*)>\s*$/i) {
+ $this_author_name = $1;
+ $this_author_email = $2;
+ } elsif (!$header_done && /^$/ { # empty line ends header.
+ $header_done = 1;
+ } else {
+ $commit_msg .= $_;
+ $header_done = 1;
+ }
+ }
+ close MSG;
+ }
+ }
+
print FI <<EOF;
commit $branch_ref
-author $author_name <$author_email> $author_time +0000
-committer $committer_name <$committer_email> $commit_time +0000
+author $this_author_name <$this_author_email> $author_time +0000
+committer $this_committer_name <$this_committer_email> $commit_time +0000
data <<END_OF_COMMIT_MESSAGE
-Imported from $tar_file.
+$commit_msg
END_OF_COMMIT_MESSAGE
deleteall
--
1.6.3.3
^ permalink raw reply related
* [PATCH] git-clone: add missing coma in --reference documentation
From: Miklos Vajna @ 2009-09-03 11:24 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>
---
Documentation/git-clone.txt | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index b14de6c..87c13ab 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -76,7 +76,7 @@ then the cloned repository will become corrupt.
--reference <repository>::
- If the reference repository is on the local machine
+ If the reference repository is on the local machine,
automatically setup .git/objects/info/alternates to
obtain objects from the reference repository. Using
an already existing repository as an alternate will
--
1.6.4
^ permalink raw reply related
* Re: [JGIT PATCH 0/5] jgit diff
From: Johannes Schindelin @ 2009-09-03 10:48 UTC (permalink / raw)
To: git, spearce
In-Reply-To: <cover.1251974493u.git.johannes.schindelin@gmx.de>
Hi,
On Thu, 3 Sep 2009, Johannes Schindelin wrote:
> This patch series provides a rudimentary, working implementation of
> "jgit diff". It does not provide all modes of "git diff" -- by far! --
> but it is robust, and should provide a good starting point for further
> work.
I forgot to mention that this is rebased to current jgit.git's master (and
tested there, too; took 713 seconds on this here machine).
Ciao,
Dscho
^ permalink raw reply
* [JGIT PATCH 5/5] Add the "jgit diff" command
From: Johannes Schindelin @ 2009-09-03 10:47 UTC (permalink / raw)
To: git, spearce
In-Reply-To: <cover.1251974493u.git.johannes.schindelin@gmx.de>
This commit contains fixes provided by Christian Halstrick.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
.../services/org.spearce.jgit.pgm.TextBuiltin | 1 +
.../src/org/spearce/jgit/pgm/Diff.java | 133 ++++++++++++++++++++
.../src/org/spearce/jgit/diff/DiffFormatter.java | 2 +-
3 files changed, 135 insertions(+), 1 deletions(-)
create mode 100644 org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Diff.java
diff --git a/org.spearce.jgit.pgm/src/META-INF/services/org.spearce.jgit.pgm.TextBuiltin b/org.spearce.jgit.pgm/src/META-INF/services/org.spearce.jgit.pgm.TextBuiltin
index 3a8cc09..107ef38 100644
--- a/org.spearce.jgit.pgm/src/META-INF/services/org.spearce.jgit.pgm.TextBuiltin
+++ b/org.spearce.jgit.pgm/src/META-INF/services/org.spearce.jgit.pgm.TextBuiltin
@@ -1,6 +1,7 @@
org.spearce.jgit.pgm.Branch
org.spearce.jgit.pgm.Clone
org.spearce.jgit.pgm.Daemon
+org.spearce.jgit.pgm.Diff
org.spearce.jgit.pgm.DiffTree
org.spearce.jgit.pgm.Fetch
org.spearce.jgit.pgm.Glog
diff --git a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Diff.java b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Diff.java
new file mode 100644
index 0000000..56e352d
--- /dev/null
+++ b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Diff.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2009, Johannes E. Schindelin
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Git Development Community nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.spearce.jgit.pgm;
+
+import java.io.IOException;
+import java.io.PrintStream;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.ExampleMode;
+import org.kohsuke.args4j.Option;
+
+import org.spearce.jgit.diff.DiffFormatter;
+import org.spearce.jgit.diff.MyersDiff;
+import org.spearce.jgit.diff.RawText;
+
+import org.spearce.jgit.lib.Constants;
+import org.spearce.jgit.lib.FileMode;
+import org.spearce.jgit.lib.ObjectId;
+import org.spearce.jgit.lib.Ref;
+
+import org.spearce.jgit.pgm.opt.CmdLineParser;
+import org.spearce.jgit.pgm.opt.PathTreeFilterHandler;
+
+import org.spearce.jgit.treewalk.AbstractTreeIterator;
+import org.spearce.jgit.treewalk.TreeWalk;
+
+import org.spearce.jgit.treewalk.filter.AndTreeFilter;
+import org.spearce.jgit.treewalk.filter.TreeFilter;
+
+@Command(common = true, usage = "Show diffs")
+class Diff extends TextBuiltin {
+ @Argument(index = 0, metaVar = "tree-ish", required = true)
+ void tree_0(final AbstractTreeIterator c) {
+ trees.add(c);
+ }
+
+ @Argument(index = 1, metaVar = "tree-ish", required = true)
+ private final List<AbstractTreeIterator> trees = new ArrayList<AbstractTreeIterator>();
+
+ @Option(name = "--", metaVar = "path", multiValued = true, handler = PathTreeFilterHandler.class)
+ private TreeFilter pathFilter = TreeFilter.ALL;
+
+ private DiffFormatter fmt = new DiffFormatter();
+
+ @Override
+ protected void run() throws Exception {
+ final TreeWalk walk = new TreeWalk(db);
+ walk.reset();
+ walk.setRecursive(true);
+ for (final AbstractTreeIterator i : trees)
+ walk.addTree(i);
+ walk.setFilter(AndTreeFilter.create(TreeFilter.ANY_DIFF, pathFilter));
+
+ final int nTree = walk.getTreeCount();
+ while (walk.next())
+ outputDiff(System.out, walk.getPathString(),
+ walk.getObjectId(0), walk.getFileMode(0),
+ walk.getObjectId(1), walk.getFileMode(1));
+ }
+
+ protected void outputDiff(PrintStream out, String path,
+ ObjectId id1, FileMode mode1, ObjectId id2, FileMode mode2) throws IOException {
+ String name1 = "a/" + path;
+ String name2 = "b/" + path;
+ out.println("diff --git " + name1 + " " + name2);
+ boolean isNew=false;
+ boolean isDelete=false;
+ if (id1.equals(id1.zeroId())) {
+ out.println("new file mode " + mode2);
+ isNew=true;
+ } else if (id2.equals(id2.zeroId())) {
+ out.println("deleted file mode " + mode1);
+ isDelete=true;
+ } else if (!mode1.equals(mode2)) {
+ out.println("old mode " + mode1);
+ out.println("new mode " + mode2);
+ }
+ out.println("index " + id1.abbreviate(db, 7).name()
+ + ".." + id2.abbreviate(db, 7).name()
+ + (mode1.equals(mode2) ? " " + mode1 : ""));
+ out.println("--- " + (isNew ? "/dev/null" : name1));
+ out.println("+++ " + (isDelete ? "/dev/null" : name2));
+ RawText a = getRawText(id1);
+ RawText b = getRawText(id2);
+ MyersDiff diff = new MyersDiff(a, b);
+ fmt.formatEdits(out, a, b, diff.getEdits());
+ }
+
+ private RawText getRawText(ObjectId id) throws IOException {
+ if (id.equals(id.zeroId()))
+ return new RawText(new byte[] { });
+ return new RawText(db.openBlob(id).getCachedBytes());
+ }
+}
+
diff --git a/org.spearce.jgit/src/org/spearce/jgit/diff/DiffFormatter.java b/org.spearce.jgit/src/org/spearce/jgit/diff/DiffFormatter.java
index fa86737..fda3f4c 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/diff/DiffFormatter.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/diff/DiffFormatter.java
@@ -108,7 +108,7 @@ public void format(final OutputStream out, final FileHeader head,
formatEdits(out, a, b, head.toEditList());
}
- private void formatEdits(final OutputStream out, final RawText a,
+ public void formatEdits(final OutputStream out, final RawText a,
final RawText b, final EditList edits) throws IOException {
for (int curIdx = 0; curIdx < edits.size();) {
Edit curEdit = edits.get(curIdx);
--
1.6.4.297.gcb4cc
^ permalink raw reply related
* [JGIT PATCH 4/5] Prepare RawText for diff-index and diff-files
From: Johannes Schindelin @ 2009-09-03 10:47 UTC (permalink / raw)
To: git, spearce
In-Reply-To: <cover.1251974493u.git.johannes.schindelin@gmx.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
.../src/org/spearce/jgit/diff/RawText.java | 28 +++++++++++++++++++-
1 files changed, 27 insertions(+), 1 deletions(-)
diff --git a/org.spearce.jgit/src/org/spearce/jgit/diff/RawText.java b/org.spearce.jgit/src/org/spearce/jgit/diff/RawText.java
index 9886d36..15d1c12 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/diff/RawText.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/diff/RawText.java
@@ -38,6 +38,8 @@
package org.spearce.jgit.diff;
+import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
@@ -81,6 +83,18 @@ public RawText(final byte[] input) {
hashes = computeHashes();
}
+ /**
+ * Create a new sequence from a file.
+ * <p>
+ * The entire file contents are used.
+ *
+ * @param file
+ * the text file.
+ */
+ public RawText(File file) throws IOException {
+ this(readFile(file));
+ }
+
public int size() {
// The line map is always 2 entries larger than the number of lines in
// the file. Index 0 is padded out/unused. The last index is the total
@@ -181,4 +195,16 @@ protected int hashLine(final byte[] raw, int ptr, final int end) {
hash = (hash << 5) ^ (raw[ptr] & 0xff);
return hash;
}
-}
\ No newline at end of file
+
+ private static byte[] readFile(File file) throws IOException {
+ byte[] result = new byte[(int)file.length()];
+ FileInputStream in = new FileInputStream(file);
+ for (int off = 0; off < result.length; ) {
+ int read = in.read(result, off, result.length - off);
+ if (read < 0)
+ throw new IOException("Early EOF");
+ off += read;
+ }
+ return result;
+ }
+}
--
1.6.4.297.gcb4cc
^ permalink raw reply related
* [JGIT PATCH 3/5] Add a test class for Myers' diff algorithm
From: Johannes Schindelin @ 2009-09-03 10:46 UTC (permalink / raw)
To: git, spearce
In-Reply-To: <cover.1251974493u.git.johannes.schindelin@gmx.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
.../tst/org/spearce/jgit/diff/MyersDiffTest.java | 103 ++++++++++++++++++++
1 files changed, 103 insertions(+), 0 deletions(-)
create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/diff/MyersDiffTest.java
diff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/diff/MyersDiffTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/diff/MyersDiffTest.java
new file mode 100644
index 0000000..0d62790
--- /dev/null
+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/diff/MyersDiffTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2009, Johannes E. Schindelin
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Git Development Community nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.spearce.jgit.diff;
+
+import junit.framework.TestCase;
+
+public class MyersDiffTest extends TestCase {
+ public void testAtEnd() {
+ assertDiff("HELLO", "HELL", " -4,1 +4,0");
+ }
+
+ public void testAtStart() {
+ assertDiff("Git", "JGit", " -0,0 +0,1");
+ }
+
+ public void testSimple() {
+ assertDiff("HELLO WORLD", "LOW",
+ " -0,3 +0,0 -5,1 +2,0 -7,4 +3,0");
+ // is ambiguous, could be this, too:
+ // " -0,2 +0,0 -3,1 +1,0 -5,1 +2,0 -7,4 +3,0"
+ }
+
+ public void assertDiff(String a, String b, String edits) {
+ MyersDiff diff = new MyersDiff(toCharArray(a), toCharArray(b));
+System.err.println("edits: " + diff.getEdits());
+ assertEquals(edits, toString(diff.getEdits()));
+ }
+
+ private static String toString(EditList list) {
+ StringBuilder builder = new StringBuilder();
+ for (Edit e : list)
+ builder.append(" -" + e.beginA
+ + "," + (e.endA - e.beginA)
+ + " +" + e.beginB + "," + (e.endB - e.beginB));
+ return builder.toString();
+ }
+
+ private static CharArray toCharArray(String s) {
+ return new CharArray(s);
+ }
+
+ protected static String toString(Sequence seq, int begin, int end) {
+ CharArray a = (CharArray)seq;
+ return new String(a.array, begin, end - begin);
+ }
+
+ protected static String toString(CharArray a, CharArray b,
+ int x, int k) {
+ return "(" + x + "," + (k + x)
+ + (x < 0 ? '<' :
+ (x >= a.array.length ?
+ '>' : a.array[x]))
+ + (k + x < 0 ? '<' :
+ (k + x >= b.array.length ?
+ '>' : b.array[k + x]))
+ + ")";
+ }
+
+ private static class CharArray implements Sequence {
+ char[] array;
+ public CharArray(String s) { array = s.toCharArray(); }
+ public int size() { return array.length; }
+ public boolean equals(int i, Sequence other, int j) {
+ CharArray o = (CharArray)other;
+ return array[i] == o.array[j];
+ }
+ }
+}
--
1.6.4.297.gcb4cc
^ permalink raw reply related
* [JGIT PATCH 2/5] Add Myers' algorithm to generate diff scripts
From: Johannes Schindelin @ 2009-09-03 10:46 UTC (permalink / raw)
To: git, spearce
In-Reply-To: <cover.1251974493u.git.johannes.schindelin@gmx.de>
Myers' algorithm is the standard way to generate diff scripts in an
efficient manner (especially memory-wise).
The source contains extensive documentation about the principal
ideas of the algorithm.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
.../src/org/spearce/jgit/diff/MyersDiff.java | 515 ++++++++++++++++++++
1 files changed, 515 insertions(+), 0 deletions(-)
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/diff/MyersDiff.java
diff --git a/org.spearce.jgit/src/org/spearce/jgit/diff/MyersDiff.java b/org.spearce.jgit/src/org/spearce/jgit/diff/MyersDiff.java
new file mode 100644
index 0000000..e19cea4
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/diff/MyersDiff.java
@@ -0,0 +1,515 @@
+/*
+ * Copyright (C) 2008-2009 Johannes E. Schindelin <johannes.schindelin@gmx.de>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Git Development Community nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Diff algorithm, based on "An O(ND) Difference Algorithm and its
+ * Variations", by Eugene Myers.
+ *
+ * The basic idea is to put the line numbers of text A as columns ("x") and the
+ * lines of text B as rows ("y"). Now you try to find the shortest "edit path"
+ * from the upper left corner to the lower right corner, where you can
+ * always go horizontally or vertically, but diagonally from (x,y) to
+ * (x+1,y+1) only if line x in text A is identical to line y in text B.
+ *
+ * Myers' fundamental concept is the "furthest reaching D-path on diagonal k":
+ * a D-path is an edit path starting at the upper left corner and containing
+ * exactly D non-diagonal elements ("differences"). The furthest reaching
+ * D-path on diagonal k is the one that contains the most (diagonal) elements
+ * which ends on diagonal k (where k = y - x).
+ *
+ * Example:
+ *
+ * H E L L O W O R L D
+ * ____
+ * L \___
+ * O \___
+ * W \________
+ *
+ * Since every D-path has exactly D horizontal or vertical elements, it can
+ * only end on the diagonals -D, -D+2, ..., D-2, D.
+ *
+ * Since every furthest reaching D-path contains at least one furthest
+ * reaching (D-1)-path (except for D=0), we can construct them recursively.
+ *
+ * Since we are really interested in the shortest edit path, we can start
+ * looking for a 0-path, then a 1-path, and so on, until we find a path that
+ * ends in the lower right corner.
+ *
+ * To save space, we do not need to store all paths (which has quadratic space
+ * requirements), but generate the D-paths simultaneously from both sides.
+ * When the ends meet, we will have found "the middle" of the path. From the
+ * end points of that diagonal part, we can generate the rest recursively.
+ *
+ * This only requires linear space.
+ *
+ * The overall (runtime) complexity is
+ *
+ * O(N * D^2 + 2 * N/2 * (D/2)^2 + 4 * N/4 * (D/4)^2 + ...)
+ * = O(N * D^2 * 5 / 4) = O(N * D^2),
+ *
+ * (With each step, we have to find the middle parts of twice as many regions
+ * as before, but the regions (as well as the D) are halved.)
+ *
+ * So the overall runtime complexity stays the same with linear space,
+ * albeit with a larger constant factor.
+ */
+
+package org.spearce.jgit.diff;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.spearce.jgit.util.IntList;
+
+public class MyersDiff {
+ protected EditList edits;
+ protected Sequence a, b;
+
+ public MyersDiff(Sequence a, Sequence b) {
+ this.a = a;
+ this.b = b;
+ calculateEdits();
+ }
+
+ public EditList getEdits() {
+ return edits;
+ }
+
+ // TODO: use ThreadLocal for future multi-threaded operations
+ MiddleEdit middle = new MiddleEdit();
+
+ protected void calculateEdits() {
+ edits = new EditList();
+
+ middle.initialize(0, a.size(), 0, b.size());
+ if (middle.beginA >= middle.endA &&
+ middle.beginB >= middle.endB)
+ return;
+
+ calculateEdits(middle.beginA, middle.endA,
+ middle.beginB, middle.endB);
+ }
+
+ protected void calculateEdits(int beginA, int endA,
+ int beginB, int endB) {
+ Edit edit = middle.calculate(beginA, endA, beginB, endB);
+
+ if (beginA < edit.beginA || beginB < edit.beginB) {
+ int k = edit.beginB - edit.beginA;
+ int x = middle.backward.snake(k, edit.beginA);
+ calculateEdits(beginA, x, beginB, k + x);
+ }
+
+ if (edit.getType() != Edit.Type.EMPTY)
+ edits.add(edits.size(), edit);
+
+ // after middle
+ if (endA > edit.endA || endB > edit.endB) {
+ int k = edit.endB - edit.endA;
+ int x = middle.forward.snake(k, edit.endA);
+ calculateEdits(x, endA, k + x, endB);
+ }
+ }
+
+ /**
+ * A class to help bisecting the sequences a and b to find minimal
+ * edit paths.
+ *
+ * As the arrays are reused for space efficiency, you will need one
+ * instance per thread.
+ *
+ * The entry function is the calculate() method.
+ */
+ class MiddleEdit {
+ void initialize(int beginA, int endA, int beginB, int endB) {
+ this.beginA = beginA; this.endA = endA;
+ this.beginB = beginB; this.endB = endB;
+
+ // strip common parts on either end
+ int k = beginB - beginA;
+ this.beginA = forward.snake(k, beginA);
+ this.beginB = k + this.beginA;
+
+ k = endB - endA;
+ this.endA = backward.snake(k, endA);
+ this.endB = k + this.endA;
+ }
+
+ /*
+ * This function calculates the "middle" Edit of the shortest
+ * edit path between the given subsequences of a and b.
+ *
+ * Once a forward path and a backward path meet, we found the
+ * middle part. From the last snake end point on both of them,
+ * we construct the Edit.
+ *
+ * It is assumed that there is at least one edit in the range.
+ */
+ // TODO: measure speed impact when this is synchronized
+ Edit calculate(int beginA, int endA, int beginB, int endB) {
+ if (beginA == endA || beginB == endB)
+ return new Edit(beginA, endA, beginB, endB);
+ this.beginA = beginA; this.endA = endA;
+ this.beginB = beginB; this.endB = endB;
+
+ /*
+ * Following the conventions in Myers' paper, "k" is
+ * the difference between the index into "b" and the
+ * index into "a".
+ */
+ int minK = beginB - endA;
+ int maxK = endB - beginA;
+
+ forward.initialize(beginB - beginA, beginA, minK, maxK);
+ backward.initialize(endB - endA, endA, minK, maxK);
+
+ for (int d = 1; ; d++)
+ if (forward.calculate(d) ||
+ backward.calculate(d))
+ return edit;
+ }
+
+ /*
+ * For each d, we need to hold the d-paths for the diagonals
+ * k = -d, -d + 2, ..., d - 2, d. These are stored in the
+ * forward (and backward) array.
+ *
+ * As we allow subsequences, too, this needs some refinement:
+ * the forward paths start on the diagonal forwardK =
+ * beginB - beginA, and backward paths start on the diagonal
+ * backwardK = endB - endA.
+ *
+ * So, we need to hold the forward d-paths for the diagonals
+ * k = forwardK - d, forwardK - d + 2, ..., forwardK + d and
+ * the analogue for the backward d-paths. This means that
+ * we can turn (k, d) into the forward array index using this
+ * formula:
+ *
+ * i = (d + k - forwardK) / 2
+ *
+ * There is a further complication: the edit paths should not
+ * leave the specified subsequences, so k is bounded by
+ * minK = beginB - endA and maxK = endB - beginA. However,
+ * (k - forwardK) _must_ be odd whenever d is odd, and it
+ * _must_ be even when d is even.
+ *
+ * The values in the "forward" and "backward" arrays are
+ * positions ("x") in the sequence a, to get the corresponding
+ * positions ("y") in the sequence b, you have to calculate
+ * the appropriate k and then y:
+ *
+ * k = forwardK - d + i * 2
+ * y = k + x
+ *
+ * (substitute backwardK for forwardK if you want to get the
+ * y position for an entry in the "backward" array.
+ */
+ EditPaths forward = new ForwardEditPaths();
+ EditPaths backward = new BackwardEditPaths();
+
+ /* Some variables which are shared between methods */
+ protected int beginA, endA, beginB, endB;
+ protected Edit edit;
+
+ abstract class EditPaths {
+ private IntList x = new IntList();
+ private IntList snake = new IntList();
+ int beginK, endK, middleK;
+ int prevBeginK, prevEndK;
+ /* if we hit one end early, no need to look further */
+ int minK, maxK; // TODO: better explanation
+
+ final int getIndex(int d, int k) {
+// TODO: remove
+if (((d + k - middleK) % 2) == 1)
+ throw new RuntimeException("odd: " + d + " + " + k + " - " + middleK);
+ return (d + k - middleK) / 2;
+ }
+
+ final int getX(int d, int k) {
+// TODO: remove
+if (k < beginK || k > endK)
+ throw new RuntimeException("k " + k + " not in " + beginK + " - " + endK);
+ return x.get(getIndex(d, k));
+ }
+
+ final int getSnake(int d, int k) {
+// TODO: remove
+if (k < beginK || k > endK)
+ throw new RuntimeException("k " + k + " not in " + beginK + " - " + endK);
+ return snake.get(getIndex(d, k));
+ }
+
+ private int forceKIntoRange(int k) {
+ /* if k is odd, so must be the result */
+ if (k < minK)
+ return minK + ((k ^ minK) & 1);
+ else if (k > maxK)
+ return maxK - ((k ^ maxK) & 1);
+ return k;
+ }
+
+ void initialize(int k, int x, int minK, int maxK) {
+ this.minK = minK;
+ this.maxK = maxK;
+ beginK = endK = middleK = k;
+ this.x.clear();
+ this.x.add(x);
+ snake.clear();
+ snake.add(newSnake(k, x));
+ }
+
+ abstract int snake(int k, int x);
+ abstract int getLeft(int x);
+ abstract int getRight(int x);
+ abstract boolean isBetter(int left, int right);
+ abstract void adjustMinMaxK(final int k, final int x);
+ abstract boolean meets(int d, int k, int x, int snake);
+
+ final int newSnake(int k, int x) {
+ int y = k + x;
+ return x + (endA + 1) * y;
+ }
+
+ final int snake2x(int snake) {
+ return snake % (endA + 1);
+ }
+
+ final int snake2y(int snake) {
+ return snake / (endA + 1);
+ }
+
+ final boolean makeEdit(int snake1, int snake2) {
+ int x1 = snake2x(snake1), x2 = snake2x(snake2);
+ int y1 = snake2y(snake1), y2 = snake2y(snake2);
+ /*
+ * Check for incompatible partial edit paths:
+ * when there are ambiguities, we might have
+ * hit incompatible (i.e. non-overlapping)
+ * forward/backward paths.
+ *
+ * In that case, just pretend that we have
+ * an empty edit at the end of one snake; this
+ * will force a decision which path to take
+ * in the next recursion step.
+ */
+ if (x1 > x2 || y1 > y2) {
+ x1 = x2;
+ y1 = y2;
+ }
+ edit = new Edit(x1, x2, y1, y2);
+ return true;
+ }
+
+ boolean calculate(int d) {
+ prevBeginK = beginK;
+ prevEndK = endK;
+ beginK = forceKIntoRange(middleK - d);
+ endK = forceKIntoRange(middleK + d);
+ // TODO: handle i more efficiently
+ // TODO: walk snake(k, getX(d, k)) only once per (d, k)
+ // TODO: move end points out of the loop to avoid conditionals inside the loop
+ // go backwards so that we can avoid temp vars
+ for (int k = endK; k >= beginK; k -= 2) {
+ int left = -1, right = -1;
+ int leftSnake = -1, rightSnake = -1;
+ // TODO: refactor into its own function
+ if (k > prevBeginK) {
+ int i = getIndex(d - 1, k - 1);
+ left = x.get(i);
+ int end = snake(k - 1, left);
+ leftSnake = left != end ?
+ newSnake(k - 1, end) :
+ snake.get(i);
+ if (meets(d, k - 1, end, leftSnake))
+ return true;
+ left = getLeft(end);
+ }
+ if (k < prevEndK) {
+ int i = getIndex(d - 1, k + 1);
+ right = x.get(i);
+ int end = snake(k + 1, right);
+ rightSnake = right != end ?
+ newSnake(k + 1, end) :
+ snake.get(i);
+ if (meets(d, k + 1, end, rightSnake))
+ return true;
+ right = getRight(end);
+ }
+ int newX, newSnake;
+ if (k >= prevEndK ||
+ (k > prevBeginK &&
+ isBetter(left, right))) {
+ newX = left;
+ newSnake = leftSnake;
+ }
+ else {
+ newX = right;
+ newSnake = rightSnake;
+ }
+ if (meets(d, k, newX, newSnake))
+ return true;
+ adjustMinMaxK(k, newX);
+ int i = getIndex(d, k);
+ x.set(i, newX);
+ snake.set(i, newSnake);
+ }
+ return false;
+ }
+ }
+
+ class ForwardEditPaths extends EditPaths {
+ final int snake(int k, int x) {
+ for (; x < endA && k + x < endB; x++)
+ if (!a.equals(x, b, k + x))
+ break;
+ return x;
+ }
+
+ final int getLeft(final int x) {
+ return x;
+ }
+
+ final int getRight(final int x) {
+ return x + 1;
+ }
+
+ final boolean isBetter(final int left, final int right) {
+ return left > right;
+ }
+
+ final void adjustMinMaxK(final int k, final int x) {
+ if (x >= endA || k + x >= endB) {
+ if (k > backward.middleK)
+ maxK = k;
+ else
+ minK = k;
+ }
+ }
+
+ final boolean meets(int d, int k, int x, int snake) {
+ if (k < backward.beginK || k > backward.endK)
+ return false;
+ // TODO: move out of loop
+ if (((d - 1 + k - backward.middleK) % 2) == 1)
+ return false;
+ if (x < backward.getX(d - 1, k))
+ return false;
+ makeEdit(snake, backward.getSnake(d - 1, k));
+ return true;
+ }
+ }
+
+ class BackwardEditPaths extends EditPaths {
+ final int snake(int k, int x) {
+ for (; x > beginA && k + x > beginB; x--)
+ if (!a.equals(x - 1, b, k + x - 1))
+ break;
+ return x;
+ }
+
+ final int getLeft(final int x) {
+ return x - 1;
+ }
+
+ final int getRight(final int x) {
+ return x;
+ }
+
+ final boolean isBetter(final int left, final int right) {
+ return left < right;
+ }
+
+ final void adjustMinMaxK(final int k, final int x) {
+ if (x <= beginA || k + x <= beginB) {
+ if (k > forward.middleK)
+ maxK = k;
+ else
+ minK = k;
+ }
+ }
+
+ final boolean meets(int d, int k, int x, int snake) {
+ if (k < forward.beginK || k > forward.endK)
+ return false;
+ // TODO: move out of loop
+ if (((d + k - forward.middleK) % 2) == 1)
+ return false;
+ if (x > forward.getX(d, k))
+ return false;
+ makeEdit(forward.getSnake(d, k), snake);
+ return true;
+ }
+ }
+ }
+
+ // debugging (TODO: remove)
+ public void print(Sequence s, int begin, int end) {
+ RawText raw = (RawText)s;
+ try {
+ while (begin < end) {
+ System.err.print("" + begin + ": ");
+ raw.writeLine(System.err, begin++);
+ System.err.println("");
+ }
+ } catch (Exception e) { e.printStackTrace(); }
+ }
+
+ public void print(int beginA, int endA, int beginB, int endB) {
+ System.err.println("<<<<<<");
+ print(a, beginA, endA);
+ System.err.println("======");
+ print(b, beginB, endB);
+ System.err.println(">>>>>>");
+ }
+
+ public static void main(String[] args) {
+ if (args.length != 2) {
+ System.err.println("Need 2 arguments");
+ System.exit(1);
+ }
+ try {
+ RawText a = new RawText(new java.io.File(args[0]));
+ RawText b = new RawText(new java.io.File(args[1]));
+ MyersDiff diff = new MyersDiff(a, b);
+ System.out.println(diff.getEdits().toString());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
--
1.6.4.297.gcb4cc
^ permalink raw reply related
* [JGIT PATCH 1/5] Add set to IntList
From: Johannes Schindelin @ 2009-09-03 10:46 UTC (permalink / raw)
To: git, spearce
In-Reply-To: <cover.1251974493u.git.johannes.schindelin@gmx.de>
Some applications may wish to modify an int list.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
.../tst/org/spearce/jgit/util/IntListTest.java | 21 ++++++++++++++++++++
.../src/org/spearce/jgit/util/IntList.java | 17 ++++++++++++++++
2 files changed, 38 insertions(+), 0 deletions(-)
diff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/util/IntListTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/util/IntListTest.java
index c470d55..a7a12cd 100644
--- a/org.spearce.jgit.test/tst/org/spearce/jgit/util/IntListTest.java
+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/util/IntListTest.java
@@ -144,6 +144,27 @@ public void testClear() {
}
}
+ public void testSet() {
+ final IntList i = new IntList();
+ i.add(1);
+ assertEquals(1, i.size());
+ assertEquals(1, i.get(0));
+
+ i.set(0, 5);
+ assertEquals(5, i.get(0));
+
+ try {
+ i.set(5, 5);
+ fail("accepted set of 5 beyond end of list");
+ } catch (ArrayIndexOutOfBoundsException e){
+ assertTrue(true);
+ }
+
+ i.set(1, 2);
+ assertEquals(2, i.size());
+ assertEquals(2, i.get(1));
+ }
+
public void testToString() {
final IntList i = new IntList();
i.add(1);
diff --git a/org.spearce.jgit/src/org/spearce/jgit/util/IntList.java b/org.spearce.jgit/src/org/spearce/jgit/util/IntList.java
index 0a84793..32d24fc 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/util/IntList.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/util/IntList.java
@@ -94,6 +94,23 @@ public void add(final int n) {
}
/**
+ * Assign an entry in the list.
+ *
+ * @param index
+ * index to set, must be in the range [0, {@link #size()}).
+ * @param n
+ * value to store at the position.
+ */
+ public void set(final int index, final int n) {
+ if (count < index)
+ throw new ArrayIndexOutOfBoundsException(index);
+ else if (count == index)
+ add(n);
+ else
+ entries[index] = n;
+ }
+
+ /**
* Pad the list with entries.
*
* @param toIndex
--
1.6.4.297.gcb4cc
^ permalink raw reply related
* [JGIT PATCH 0/5] jgit diff
From: Johannes Schindelin @ 2009-09-03 10:45 UTC (permalink / raw)
To: git, spearce
In-Reply-To: <alpine.DEB.1.00.0909030846230.8306@pacific.mpi-cbg.de>
This patch series provides a rudimentary, working implementation of "jgit
diff". It does not provide all modes of "git diff" -- by far! -- but it
is robust, and should provide a good starting point for further work.
Unfortunately, I lack the time to do proper profiling/benchmarking, but I
verified at least that it succeeds in recreating valid patches for all
commits in jgit.git with this script:
git rev-list HEAD |
sed '$d' |
while read commit
do
printf "\\r$commit "
(export GIT_INDEX_FILE=test-index &&
./jgit diff $commit^ $commit > test-patch &&
git read-tree $commit^ &&
git apply --cached test-patch &&
git diff --exit-code --cached $commit) || break
done
Johannes Schindelin (5):
Add set to IntList
Add Myers' algorithm to generate diff scripts
Add a test class for Myers' diff algorithm
Prepare RawText for diff-index and diff-files
Add the "jgit diff" command
.../services/org.spearce.jgit.pgm.TextBuiltin | 1 +
.../src/org/spearce/jgit/pgm/Diff.java | 133 +++++
.../tst/org/spearce/jgit/diff/MyersDiffTest.java | 103 ++++
.../tst/org/spearce/jgit/util/IntListTest.java | 21 +
.../src/org/spearce/jgit/diff/DiffFormatter.java | 2 +-
.../src/org/spearce/jgit/diff/MyersDiff.java | 515 ++++++++++++++++++++
.../src/org/spearce/jgit/diff/RawText.java | 28 +-
.../src/org/spearce/jgit/util/IntList.java | 17 +
8 files changed, 818 insertions(+), 2 deletions(-)
create mode 100644 org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Diff.java
create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/diff/MyersDiffTest.java
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/diff/MyersDiff.java
^ permalink raw reply
* Hosting Git repositories: how useful will git-gc be?
From: Matthieu Moy @ 2009-09-03 9:45 UTC (permalink / raw)
To: git
Hi,
I'm helping my sysadmin to set up some Git repository hosting via
gitosis. I'm trying to keep it as simple as possible.
A question: is it necessary/recommanded/useless to set up a cron job
doing a "git gc" in each repository? My understanding is that a push
through ssh will do some packing, is it correct? Does receiving a pack
trigger a "git gc --auto"?
Thanks,
--
Matthieu Moy
http://www-verimag.imag.fr/~moy/
^ permalink raw reply
* Re: [PATCHv2] git-config: Parse config files leniently
From: Michael J Gruber @ 2009-09-03 7:41 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vab1cfr6s.fsf@alter.siamese.dyndns.org>
Junio C Hamano venit, vidit, dixit 03.09.2009 09:00:
> Michael J Gruber <git@drmicha.warpmail.net> writes:
>
>> Currently, git config dies as soon as there is a parsing error. This is
>> especially unfortunate in case a user tries to correct config mistakes
>> using git config -e.
>>
>> Instead, issue a warning only and treat the rest of the line as a
>> comment (ignore it). This benefits not only git config -e users but
>> also everyone else.
>
> This changes the behaviour enough to break t3200-branch.sh, test #52.
>
> The test stuffs an invalid (but not syntactically incorrect) value used by
> "git branch" in the configuration and tries to make sure that "git branch"
> diagnoses the breakage, but it does not fail anymore with your patch.
>
> There are probably other breakages as well (e.g. t5304-prune.sh, test #5)
> but if you trace "git branch" under the debugger in the trash directory
> left after running t3200 with -i, it should be pretty obvious that your
> patch is utterly bogus. get_value() can return negative result after
> diagnosing a semantic problem with the value, and that is different from a
> syntax error that you would try to recover and continue, pretending you
> can ignore the remainder of the line as if it is a comment.
>
> Why was I CC'ed, if the patch wasn't even self tested?
Because
- not CC'ing you would have meant culling you from the existing CC,
- we've discussed v1 of this patch before,
- I asked in this patch (v2) whether to go for an alternative.
Since "git config -e" for broken config is not my itch at all, but the
reporter's, I'll stop my efforts after this response.
Michael
^ permalink raw reply
* Re: [PATCHv2] git-config: Parse config files leniently
From: Junio C Hamano @ 2009-09-03 7:00 UTC (permalink / raw)
To: Michael J Gruber; +Cc: git
In-Reply-To: <f29b5893b7022f53d380504fe201303acd9ee3da.1251922441.git.git@drmicha.warpmail.net>
Michael J Gruber <git@drmicha.warpmail.net> writes:
> Currently, git config dies as soon as there is a parsing error. This is
> especially unfortunate in case a user tries to correct config mistakes
> using git config -e.
>
> Instead, issue a warning only and treat the rest of the line as a
> comment (ignore it). This benefits not only git config -e users but
> also everyone else.
This changes the behaviour enough to break t3200-branch.sh, test #52.
The test stuffs an invalid (but not syntactically incorrect) value used by
"git branch" in the configuration and tries to make sure that "git branch"
diagnoses the breakage, but it does not fail anymore with your patch.
There are probably other breakages as well (e.g. t5304-prune.sh, test #5)
but if you trace "git branch" under the debugger in the trash directory
left after running t3200 with -i, it should be pretty obvious that your
patch is utterly bogus. get_value() can return negative result after
diagnosing a semantic problem with the value, and that is different from a
syntax error that you would try to recover and continue, pretending you
can ignore the remainder of the line as if it is a comment.
Why was I CC'ed, if the patch wasn't even self tested?
^ permalink raw reply
* jgit diff, was Re: [JGIT] Request for help
From: Johannes Schindelin @ 2009-09-03 6:55 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: Nasser Grainawi, Git Mailing List
In-Reply-To: <20090903012207.GF1033@spearce.org>
Hi,
On Wed, 2 Sep 2009, Shawn O. Pearce wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> > On Wed, 2 Sep 2009, Nasser Grainawi wrote:
> >
> > > I'm looking to add 'git patch-id' to JGit and I could use a few
> > > pointers. I'm not very familiar with the JGit code base or Java, so
> > > please excuse any blatant oversights or unintelligent questions.
> > >
> > > First off, is there a "hacking JGit" document anywhere? One of those
> > > would be great right now.
> >
> > There have been some mails with details about JGit from Shawn (IIRC)
> > to this very list.
>
> Yea, for the most part I think we use Eclipse, and you just have to
> import JGit's top level directory into Eclipse as it comes with Eclipse
> project files. But I know some folks only use our Maven build (under
> jgit-maven/jgit) or use NetBeans. I have no idea how to import the
> project into the latter or configure its unit tests to run.
FWIW I use vim & shell most of the time (yes, even for JGit).
> > This is not really difficult in Java, however, it relies on a working
> > diff implementation (and IIRC my implementation has not yet been
> > integrated into JGit).
>
> Speaking of... where does that stand?
Same as where I left off. IOW it is a working implementation that saw
some testing, but I simply lack the time for performance tuning.
It should not be all that bad, though.
***goes looking at
http://repo.or.cz/w/jgit/dscho.git?a=shortlog;h=refs/heads/diff
***
Seems I misremembered a bit. Christian provided a patch to make it
compileable, but I think that I ran the script to verify that the diffs
are correct on jgit.git and IIRC it completed fine.
There is a project in my day-job, however, which eats all my time at the
moment (it is actually wrapping up a "succeeded" GSoC project where the
student -- *sigh* -- has gone away). So all I can do is to rebase to
current jgit.git's 's master, to run the script, and submit the current
patch series (valuing correctness over speed).
Ciao,
Dscho
^ permalink raw reply
* Re: [PATCH v6 5/6] fast-import: add option command
From: Sverre Rabbelier @ 2009-09-03 4:55 UTC (permalink / raw)
To: Junio C Hamano
Cc: Shawn O. Pearce, Johannes Schindelin, Git List, Ian Clatworthy,
Matt McClure, Miklos Vajna, Julian Phillips, vcs-fast-import-devs
In-Reply-To: <7vskf4px6j.fsf@alter.siamese.dyndns.org>
Heya,
On Thu, Sep 3, 2009 at 04:41, Junio C Hamano<gitster@pobox.com> wrote:
> If "option git something-unknown" is given, it is clear that the tool that
> generated the stream assumed that such an option exists in the importer;
> it might appear prudent to abort the operation.
>
> But what about "option hg something"?
I think we should assume that if we see 'option not-us foo' without a
preceeding 'feature not-us-option', the frontend does not require us
to understand the option (perhaps because they also specify 'option
git foo'.
> If that is the sensible thing to do, then we obviously should ignore
> "option hg anything", but at the same time we should ignore "option git
> we-do-not-know-what-it-does".
Perhaps, frontends could then use 'feature git-quiet-option' if it
wants to make sure it is supported.
> I think at least the function should be made conditional to die() if it
> was called from parse_argv() but simply ignore unknown if it was called
> from the input stream.
Makes sense, what do the fast-import devs think?
>> +static void parse_option(void)
>> +{
>> + char* option = command_buf.buf + 11;
>
> ERROR: "foo* bar" should be "foo *bar"
Ah, I thought I had fixed all of those, apologies.
> ERROR: do not use C99 // comments
> ERROR: do not use C99 // comments
Will fix in the next version (after we decide on what to do with
unknown git options).
--
Cheers,
Sverre Rabbelier
^ permalink raw reply
* Re: [PATCH v6 5/6] fast-import: add option command
From: Junio C Hamano @ 2009-09-03 2:41 UTC (permalink / raw)
To: Sverre Rabbelier
Cc: Shawn O. Pearce, Johannes Schindelin, Git List, Ian Clatworthy,
Matt McClure, Miklos Vajna, Julian Phillips, vcs-fast-import-devs
In-Reply-To: <1251914223-31435-6-git-send-email-srabbelier@gmail.com>
Sverre Rabbelier <srabbelier@gmail.com> writes:
> Main difference with v5 is that the syntax is now 'option git ...'
> as per a discussion with the other fast-import devs. Other options,
> e.g. 'option hg' are ignored. Also fixed the docs to say that
> feature commands are allowed before git option commands.
Perhaps the other people have discussed and thought about this much deeper
than I have after seeing the above description, but what should the
semantics be when you see unknown options?
If "option git something-unknown" is given, it is clear that the tool that
generated the stream assumed that such an option exists in the importer;
it might appear prudent to abort the operation.
But what about "option hg something"?
It is an indication that the stream is meant to be used with the named
option if fed to Hg, but it does not say anything about what should happen
when used with other systems. If older versions of Hg that do not grok
the given option is expected to abort because they won't be able to change
the behaviour to obey the optional semantics demanded by the "option hg
something", what should the other VCS do?
Worrying about the above would be unnecessary, if you declare that it is
*entirely* optional to understand and obey "option", and ignoring them
does not result in a corrupt import at all. I think that is the intent
behind "option", as opposed to "feature", and is consistent with the fact
that the command line options can override the in-stream settings. In
other words, any in-stream instruction that changes the semantics of
stream to render it dangerous to be processed by older version of tools
would be expressed with "feature", not with "option".
If that is the sensible thing to do, then we obviously should ignore
"option hg anything", but at the same time we should ignore "option git
we-do-not-know-what-it-does".
But then, the call to die("Unsupported option: %s", option) at the end of
parse_one_option() is wrong, isn't it?
I think at least the function should be made conditional to die() if it
was called from parse_argv() but simply ignore unknown if it was called
from the input stream.
> diff --git a/fast-import.c b/fast-import.c
> index 9bf06a4..bad93dc 100644
> --- a/fast-import.c
> +++ b/fast-import.c
> @@ -2456,11 +2468,31 @@ static void parse_feature(void)
>
> if (!prefixcmp(feature, "date-format=")) {
> option_date_format(feature + 12);
> + } else if (!strcmp("git-options", feature)) {
> + options_enabled = 1;
> } else {
> die("This version of fast-import does not support feature %s.", feature);
> }
> }
>
> +static void parse_option(void)
> +{
> + char* option = command_buf.buf + 11;
ERROR: "foo* bar" should be "foo *bar"
> +
> + if (!options_enabled)
> + die("Got option command '%s' before options feature'", option);
> +
> + if (seen_non_option_command)
> + die("Got option command '%s' after non-option command", option);
> +
> + parse_one_option(option);
> +}
> +
> +static void parse_nongit_option(void)
> +{
> + // do nothing
ERROR: do not use C99 // comments
> @@ -2539,9 +2581,18 @@ int main(int argc, const char **argv)
> parse_progress();
> else if (!prefixcmp(command_buf.buf, "feature "))
> parse_feature();
> + else if (!prefixcmp(command_buf.buf, "option git "))
> + parse_option();
> + else if (!prefixcmp(command_buf.buf, "option "))
> + parse_nongit_option();
> else
> die("Unsupported command: %s", command_buf.buf);
> }
> +
> + // argv hasn't been parsed yet, do so
ERROR: do not use C99 // comments
^ permalink raw reply
* Re: [JGIT] Request for help
From: Shawn O. Pearce @ 2009-09-03 1:23 UTC (permalink / raw)
To: Nasser Grainawi; +Cc: Git Mailing List
In-Reply-To: <4A9EFFB1.9090501@codeaurora.org>
Nasser Grainawi <nasser@codeaurora.org> wrote:
> Should PatchId be a class on its own, or just a method within the Patch
> class?
Hmm, maybe a method on Patch is reasonable.
--
Shawn.
^ permalink raw reply
* Re: [JGIT] Request for help
From: Shawn O. Pearce @ 2009-09-03 1:22 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Nasser Grainawi, Git Mailing List
In-Reply-To: <alpine.DEB.1.00.0909030157090.8306@pacific.mpi-cbg.de>
Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> On Wed, 2 Sep 2009, Nasser Grainawi wrote:
>
> > I'm looking to add 'git patch-id' to JGit and I could use a few
> > pointers. I'm not very familiar with the JGit code base or Java, so
> > please excuse any blatant oversights or unintelligent questions.
> >
> > First off, is there a "hacking JGit" document anywhere? One of those
> > would be great right now.
>
> There have been some mails with details about JGit from Shawn (IIRC) to
> this very list.
Yea, for the most part I think we use Eclipse, and you just have
to import JGit's top level directory into Eclipse as it comes with
Eclipse project files. But I know some folks only use our Maven
build (under jgit-maven/jgit) or use NetBeans. I have no idea how
to import the project into the latter or configure its unit tests
to run.
> > So far I'm just trying to define the inputs and outputs. On Shawn's
> > suggestion I'm planning on making it part of the org.spearce.jgit.patch
> > package. C Git patch-id very generically has an input of a 'patch', so
> > I'm thinking this implementation should use the Patch object.
>
> C Git patch-id takes a valid patch as input; I do not think that you want
> to use the Patch object.
I think we do want to use the Patch object. The Patch entity in
JGit is a parsed representation of the git diff or unified diff
structure. Its relatively easy to walk over, and all of the mess
about determining line type has already been done.
We'd probably want to do something that is a lot like the object
Patch as the output of our diff routine. A tool (e.g. Gerrit Code
Review) might only want the EditList for a given file, and not
really care about the actual formatted patch text, as it reformats
everything itself. I think patch-id computation is along those
same lines.
If we were to compute a patch-id off an InputStream we would probably
just send it through the Patch object first.
> This is not really difficult in Java, however, it relies on a working diff
> implementation (and IIRC my implementation has not yet been integrated
> into JGit).
Speaking of... where does that stand?
--
Shawn.
^ permalink raw reply
* Re: [PATCH v2] status: list unmerged files last
From: David Aguilar @ 2009-09-03 1:12 UTC (permalink / raw)
To: Jeff King; +Cc: Junio C Hamano, Johannes Sixt, bill lam, git
In-Reply-To: <20090902175908.GA5998@coredump.intra.peff.net>
On Wed, Sep 02, 2009 at 01:59:08PM -0400, Jeff King wrote:
> On Wed, Sep 02, 2009 at 03:07:32AM -0700, David Aguilar wrote:
>
> > I agree with all of this but would also add that we can have
> > our cake and eat it too with respect to wanting to "keep
> > similar things together" and having "unmerged near bottom".
>
> Well, my point was that the "bottom" is not really cake, but I am not
> sure anyone else agrees.
>
> > No one has suggested this, so I figured I would.
> > What do you think about this layout?
> >
> > - untracked
> > - staged
> > - modified
> > - unmerged
>
> What about the current branch? Alternate author info? Tracking branch
> relationship? Should those be at the top or bottom?
>
> I dunno. Maybe it is just me being crotchety and hating change, but I
> like the current order (though swapping it below "updated" is fine with
> me).
Nah, you're right.
Being crotchety and hating change is a good thing here.
> If you want to know "what does commit --amend do", then shouldn't you be
> using "git commit --amend --dry-run" (which is what "git status" is now,
> but will not be in v1.7.0)?
>
> Are there other uses cases for arbitrary tree-ish's?
>
> > BTW is status -s intended to be something plumbing-like;
> > something we can build upon and expect to be stable?
> > I'm just curious because other commands have a --porcelain
> > option and I wasn't sure if this was the intent.
>
> We mentioned a --porcelain option in other discussion, but I don't think
> there is a patch. I would be in favor of --porcelain, even if it is
> currently identical to --short, because then it gives us freedom to
> diverge later (and in particular it gives us the freedom to let user
> configuration affect what is shown).
>
> -Peff
The only use case would be for --amend.
Which is why I asked about --porcelain; really what I want is
something like
git status --porcelain HEAD^
Rolling a patch to make --porcelain an alias for --short seems
like a good idea. If we want to support HEAD^ and HEAD^ only
then perhaps an --amend flag is useful.
The real crux of my question was about being able to script
it, which is why commit --dry-run is not enough.
--
David
^ permalink raw reply
* Re: [JGIT] Request for help
From: Johannes Schindelin @ 2009-09-03 0:04 UTC (permalink / raw)
To: Nasser Grainawi; +Cc: Git Mailing List, Shawn O. Pearce
In-Reply-To: <4A9EFFB1.9090501@codeaurora.org>
Hi,
On Wed, 2 Sep 2009, Nasser Grainawi wrote:
> I'm looking to add 'git patch-id' to JGit and I could use a few
> pointers. I'm not very familiar with the JGit code base or Java, so
> please excuse any blatant oversights or unintelligent questions.
>
> First off, is there a "hacking JGit" document anywhere? One of those
> would be great right now.
There have been some mails with details about JGit from Shawn (IIRC) to
this very list.
> So far I'm just trying to define the inputs and outputs. On Shawn's
> suggestion I'm planning on making it part of the org.spearce.jgit.patch
> package. C Git patch-id very generically has an input of a 'patch', so
> I'm thinking this implementation should use the Patch object.
C Git patch-id takes a valid patch as input; I do not think that you want
to use the Patch object.
FWIW a patch-id is nothing else than the SHA-1 of a diff where the "diff",
"index", "@@" lines and all the whitespace was removed.
This is not really difficult in Java, however, it relies on a working diff
implementation (and IIRC my implementation has not yet been integrated
into JGit).
Ciao,
Dscho
^ permalink raw reply
* [JGIT] Request for help
From: Nasser Grainawi @ 2009-09-02 23:28 UTC (permalink / raw)
To: Git Mailing List; +Cc: Shawn O. Pearce
Hello all,
I'm looking to add 'git patch-id' to JGit and I could use a few
pointers. I'm not very familiar with the JGit code base or Java, so
please excuse any blatant oversights or unintelligent questions.
First off, is there a "hacking JGit" document anywhere? One of those
would be great right now.
So far I'm just trying to define the inputs and outputs. On Shawn's
suggestion I'm planning on making it part of the org.spearce.jgit.patch
package. C Git patch-id very generically has an input of a 'patch', so
I'm thinking this implementation should use the Patch object. Looking at
that class it seems that has everything patch-id should need, so perhaps
that's the only input.
As far as output, C Git patch-id has the special feature to output the
commit-id along with the patch-id when it gets input in the format of
git-diff-tree. Should JGit do the same or just return the patch-id? I
don't know that this question even makes sense in the context of JGit
(since the commit-id is almost certainly available elsewhere and someone
calling 'getPatchId()' is likely only interested in the patch-id).
Should PatchId be a class on its own, or just a method within the Patch
class?
Thanks,
Nasser
^ 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