1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-11-16 14:04:52 +01:00
Commit graph

54 commits

Author SHA1 Message Date
Junio C Hamano
005f85d9ae Use pretend_sha1_file() in git-blame and git-merge-recursive.
git-merge-recursive wants an null tree as the fake merge base
while producing the merge result tree.  The null tree does not
have to be written out in the object store as it won't be part
of the result, and it is a prime example for using the new
pretend_sha1_file() function.

git-blame needs to register an arbitrary data to in-core index
while annotating a working tree file (or standard input), but
git-blame is a read-only application and the user of it could
even lack the privilege to write into the object store; it is
another good example for pretend_sha1_file().

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-05 14:55:11 -08:00
Shawn O. Pearce
183d79724f Keep untracked files not involved in a merge.
My earlier fix (8371234e) to delete renamed tracked files from the
working directory also caused merge-recursive to delete untracked
files that were in the working directory.

The problem here is merge-recursive is deleting the working directory
file without regard for which branch it was associated with.  What we
really want to do during a merge is to only delete files that were
renamed by the branch we are merging into the current branch,
and that are still tracked by the current branch.  These files
definitely don't belong in the working directory anymore.

Anything else is either a merge conflict (already handled in other
parts of the code) or a file that is untracked by the current branch
and thus is not even participating in the merge.  Its this latter
class that must be left alone.

For this fix to work we are now assuming that the first non-base
argument passed to git-merge-recursive always corresponds to the
working directory.  This is already true for all in-tree callers
of merge-recursive.  This assumption is also supported by the
long time usage message of "<base> ... -- <head> <remote>", where
"<head>" is implied to be HEAD, which is generally assumed to be
the current tree-ish.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-03 22:04:28 -08:00
Pavel Roskin
3dff5379bf Assorted typo fixes
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-03 21:49:54 -08:00
Shawn O. Pearce
89f40be294 Convert output messages in merge-recursive to past tense.
Now that we are showing the output messages for verbosity levels
<5 after all actions have been performed (due to the progress meter
running during the actions) it can be confusing to see messages in
the present tense when the user is looking at a '100% done' message
right above them.  Converting the messages to past tense will appear
more correct in this case, and shouldn't affect a developer who is
debugging the application and running it at a verbosity level >=5.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-14 12:20:39 -08:00
Shawn O. Pearce
3f6ee2d15a Display a progress meter during merge-recursive.
Because large merges on slow systems can take up to a minute to
execute we should try to keep the user entertained with a progress
meter to let them know how far we have progressed through the
current merge.

The progress meter considers each entry in the in-memory index to
be a unit, which means a single recursive merge will double the
number of units in the progress meter.  Files which are unmerged
after the 3-way tree merge are also considered a unit within the
progress meter.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-14 12:20:39 -08:00
Shawn O. Pearce
66a155bc12 Enable output buffering in merge-recursive.
Buffering all message output until a merge invocation is complete is
necessary to prevent intereferring with a progress meter that would
indicate the number of files completely merged, and how many remain.
This change does not introduce a progress meter, but merely lays
the groundwork to buffer the output.

To aid debugging output buffering is only enabled if verbosity
is lower than 5.  When using verbosity levels above 5 the user is
probably debugging the merge program itself and does not want to
see the output delayed, especially if they are stepping through
portions of the code in a debugger.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-14 12:20:39 -08:00
Shawn O. Pearce
8c3275abca Allow the user to control the verbosity of merge-recursive.
Junio C Hamano <junkio@cox.net> writes:
>
> I think the output from merge-recursive can be categorized into 5
> verbosity levels:
>
> 1. "CONFLICT", "Rename", "Adding here instead due to D/F conflict"
> (outermost)
>
> 2. "Auto-merged successfully" (outermost)
>
> 3. The first "Merging X with Y".
>
> 4. outermost "Merging:\ntitle1\ntitle2".
>
> 5. outermost "found N common ancestors\nancestor1\nancestor2\n..."
> and anything from inner merge.
>
> I would prefer the default verbosity level to be 2 (that is, show
> both 1 and 2).

and this change makes it so.  I think level 3 is probably pointless
as its only one line of output above level 2, but I can see how some
users may want to view it but not view the slightly more verbose
output of level 4.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-14 12:20:39 -08:00
Shawn O. Pearce
63889639bb Remove unnecessary call_depth parameter in merge-recursive.
Because the output_indent always matches the call_depth value
there is no reason to pass around the call_depth to the merge
function during each recursive invocation.

This is a simple refactoring that will make the code easier to
follow later on as I start to add output verbosity controls.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-14 12:20:39 -08:00
Junio C Hamano
1cf716a219 merge-recursive: do not report the resulting tree object name
It is not available in the outermost merge, and it is only
useful for debugging merge-recursive in the inner merges.

Sergey Vlasov noticed that the old code accesses an
uninitialized location.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-12 12:05:58 -08:00
Junio C Hamano
8b944b5678 merge-recursive: do not use on-file index when not needed.
This revamps the merge-recursive implementation following the
outline in:

	Message-ID: <7v8xgileza.fsf@assigned-by-dhcp.cox.net>

There is no need to write out the index until the very end just
once from merge-recursive.  Also there is no need to write out
the resulting tree object for the simple case of merging with a
single merge base.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-10 14:45:20 -08:00
Alex Riesen
f5184380f0 Speed-up recursive by flushing index only once for all entries
The merge-recursive implementation in C inherited the invariant
that the on-file index file is written out and later read back
after any index operations and writing trees from the original
Python implementation.  But it was only because the original
implementation worked at the scripting level.

There is no need to write out the index file after handling
every path.

Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-10 14:45:20 -08:00
Andy Whitcroft
93822c2239 short i/o: fix calls to write to use xwrite or write_in_full
We have a number of badly checked write() calls.  Often we are
expecting write() to write exactly the size we requested or fail,
this fails to handle interrupts or short writes.  Switch to using
the new write_in_full().  Otherwise we at a minimum need to check
for EINTR and EAGAIN, where this is appropriate use xwrite().

Note, the changes to config handling are much larger and handled
in the next patch in the sequence.

Signed-off-by: Andy Whitcroft <apw@shadowen.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-08 15:44:47 -08:00
Shawn O. Pearce
a970e84e8a Allow merging bare trees in merge-recursive.
To support wider use cases, such as from within `git am -3`, the
merge-recursive utility needs to accept not just commit-ish but
also tree-ish as arguments on its command line.

If given a tree-ish then merge-recursive will create a virtual commit
wrapping it, with the subject of the commit set to the best name we
can derive for that tree, which is either the command line string
(probably the SHA1), or whatever string appears in GITHEAD_*.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-12-28 19:06:16 -08:00
Shawn O. Pearce
7ba3c078c7 Move better_branch_name above get_ref in merge-recursive.
To permit the get_ref function to use the static better_branch_name
function to generate a string on demand I'm moving it up earlier.
The actual logic was not affected in this change.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-12-28 19:06:16 -08:00
Shawn O. Pearce
e0ec18192d Display 'theirs' branch name when possible in merge.
Displaying the SHA1 of 'their' branch (the branch being merged into
the current branch) is not nearly as friendly as just displaying
the name of that branch, especially if that branch is already local
to this repository.

git-merge now sets the environment variable 'GITHEAD_%(sha1)=%(name)'
for each argument it gets passed, making the actual input name that
resolved to the commit '%(sha1)' easily available to the invoked
merge strategy.

git-merge-recursive makes use of these environment variables when
they are available by using '%(name)' whenever it outputs the commit
identification rather than '%(sha1)'.  This is most obvious in the
conflict hunks created by xdl_merge:

  $ git mege sideb~1
  <<<<<<< HEAD:INSTALL
     Good!
  =======
     Oops.
  >>>>>>> sideb~1:INSTALL

[jc: adjusted a test script and a minor constness glitch.]

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-12-23 01:29:37 -08:00
Shawn O. Pearce
d9606e85cd Use extended SHA1 syntax in merge-recursive conflicts.
When we get a line-level conflict in merge-recursive and print out
the two sides in the conflict hunk header and footer we should use
the standard extended SHA1 syntax to specify the specific blob,
as this allows the user to copy and paste the line right into
'git show' to view the complete version.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-12-23 01:08:02 -08:00
Junio C Hamano
aa1cef54a2 Merge branch 'jc/clone'
* jc/clone:
  Move "no merge candidate" warning into git-pull
  Use preprocessor constants for environment variable names.
  Do not create $GIT_DIR/remotes/ directory anymore.
  Introduce GIT_TEMPLATE_DIR
  Revert "fix testsuite: make sure they use templates freshly built from the source"
  fix testsuite: make sure they use templates freshly built from the source
  git-clone: lose the traditional 'no-separate-remote' layout
  git-clone: lose the artificial "first" fetch refspec
  git-pull: refuse default merge without branch.*.merge
  git-clone: use wildcard specification for tracking branches
2006-12-20 13:56:14 -08:00
Junio C Hamano
85023577a8 simplify inclusion of system header files.
This is a mechanical clean-up of the way *.c files include
system header files.

 (1) sources under compat/, platform sha-1 implementations, and
     xdelta code are exempt from the following rules;

 (2) the first #include must be "git-compat-util.h" or one of
     our own header file that includes it first (e.g. config.h,
     builtin.h, pkt-line.h);

 (3) system headers that are included in "git-compat-util.h"
     need not be included in individual C source files.

 (4) "git-compat-util.h" does not have to include subsystem
     specific header files (e.g. expat.h).

Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-12-20 09:51:35 -08:00
Junio C Hamano
d4ebc36c5e Use preprocessor constants for environment variable names.
We broke the discipline Linus set up to allow compiler help us
avoid typos in environment names in the early days of git over
time.  This defines a handful preprocessor constants for
environment variable names used in relatively core parts of the
system.

I've left out variable names specific to subsystems such as HTTP
and SSL as I do not think they are big problems.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-12-19 01:51:51 -08:00
Junio C Hamano
e4d45dd3bb Merge branch 'js/merge'
* js/merge:
  merge-recursive: add/add really is modify/modify with an empty base
  Get rid of the dependency on RCS' merge program
  merge-file: support -p and -q; fix compile warnings
  Add builtin merge-file, a minimal replacement for RCS merge
  xdl_merge(): fix and simplify conflict handling
  xdl_merge(): fix thinko
  xdl_merge(): fix an off-by-one bug
  merge-recursive: use xdl_merge().
  xmerge: make return value from xdl_merge() more usable.
  xdiff: add xdl_merge()
2006-12-13 10:46:23 -08:00
Shawn Pearce
8371234eca Remove uncontested renamed files during merge.
Prior to 65ac6e9c3f we deleted a file
from the working directory during a merge if the file existed before
the merge started but was renamed by the branch being merged in.
This broke in 65ac6e as git-merge-recursive did not actually update
the working directory on an uncontested rename.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-12-13 09:13:21 -08:00
Johannes Schindelin
f953831e03 merge-recursive: add/add really is modify/modify with an empty base
Unify the handling for cases C (add/add) and D (modify/modify).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-12-12 21:55:37 -08:00
Junio C Hamano
8042ed1ceb Merge branch 'master' into js/merge
* master: (42 commits)
  git-svn: correctly handle packed-refs in refs/remotes/
  add test case for recursive merge
  git-svn: correctly display fatal() error messages
  git-svn: allow dcommit to take an alternate head
  git-svn: enable logging of information not supported by git
  Clarify fetch error for missing objects.
  Move Fink and Ports check to after config file
  shortlog: fix segfault on empty authorname
  shortlog: remove "[PATCH]" prefix from shortlog output
  Make sure the empty tree exists when needed in merge-recursive.
  Don't use memcpy when source and dest. buffers may overlap
  no need to install manpages as executable
  Documentation: simpler shared repository creation
  shortlog: fix segfault on empty authorname
  Add branch.*.merge warning and documentation update
  Fix perl/ build.
  git-svn: use do_switch for --follow-parent if the SVN library supports it
  Fix documentation copy&paste typo
  git-svn: extra error check to ensure we open a file correctly
  Documentation: update git-clone man page with new behavior
  ...
2006-12-12 21:52:19 -08:00
Shawn O. Pearce
9abd46a347 Make sure the empty tree exists when needed in merge-recursive.
There are some baseless merge cases where git-merge-recursive will
try to compare one of the branches against the empty tree.  However
most projects won't have the empty tree object in their object database
as Git does not normally create empty tree objects.  If the empty tree
object is missing then the merge process will die, as it cannot load the
object from the database.  The error message may make the user think that
their database is corrupt when its actually not.

So instead we should just create the empty tree object whenever it is
needed.  If the object already exists as a loose object then no harm
done.  Otherwise that loose object will be pruned away later by either
git-prune or git-prune-packed.

Thanks goes to Junio for suggesting this fix.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-12-11 14:11:40 -08:00
Junio C Hamano
c2b4faea45 merge-recursive: use xdl_merge().
This seem to pass the existing tests already.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-12-02 17:28:19 -08:00
Junio C Hamano
d0a75a179e Merge branch 'jc/read-tree'
* jc/read-tree:
  t6022: ignoring untracked files by merge-recursive when they do not matter
  merge-recursive: adjust to loosened "working file clobbered" check
  merge-recursive: make a few functions static.
  merge-recursive: use abbreviated commit object name.
  merge: loosen overcautious "working file will be lost" check.
2006-11-07 15:41:34 -08:00
Alex Riesen
9faed78f59 merge-recursive implicitely depends on trust_executable_bit
Read the configuration in to get core.filemode value for this
particular repository.

Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-06 08:42:02 -08:00
Junio C Hamano
65ac6e9c3f merge-recursive: adjust to loosened "working file clobbered" check
The three-way merge by git-read-tree does not complain about
presense of the file in the working tree that is involved in a
merge when the merge result needs to be determined by the
caller.  Adjust merge-recursive so that it makes sure that an
untracked file is not touched when the merge decides the path
should not be included in the final result.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-10-27 17:16:40 -07:00
Junio C Hamano
9fe0d87da3 merge-recursive: make a few functions static.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-10-27 17:16:40 -07:00
Junio C Hamano
9926ba98a4 merge-recursive: use abbreviated commit object name.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-10-27 17:16:40 -07:00
Rene Scharfe
abdc3fc842 Add hash_sha1_file()
Most callers of write_sha1_file_prepare() are only interested in the
resulting hash but don't care about the returned file name or the header.
This patch adds a simple wrapper named hash_sha1_file() which does just
that, and converts potential callers.

Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-10-14 11:49:52 -07:00
Shawn Pearce
9befac470b Replace uses of strdup with xstrdup.
Like xmalloc and xrealloc xstrdup dies with a useful message if
the native strdup() implementation returns NULL rather than a
valid pointer.

I just tried to use xstrdup in new code and found it to be missing.
However I expected it to be present as xmalloc and xrealloc are
already commonly used throughout the code.

[jc: removed the part that deals with last_XXX, which I am
 finding more and more dubious these days.]

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-02 03:24:37 -07:00
Jonas Fonseca
2d7320d0b0 Use xmalloc instead of malloc
Signed-off-by: Jonas Fonseca <fonseca@diku.dk>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-31 16:24:39 -07:00
Junio C Hamano
87cb004e42 hashcpy/hashcmp remaining bits.
This fixes up merge-recursive.c for hashcpy/hashcmp changes.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 14:31:20 -07:00
Shawn Pearce
8da7149394 Convert memcpy(a,b,20) to hashcpy(a,b).
This abstracts away the size of the hash values when copying them
from memory location to memory location, much as the introduction
of hashcmp abstracted away hash value comparsion.

A few call sites were using char* rather than unsigned char* so
I added the cast rather than open hashcpy to be void*.  This is a
reasonable tradeoff as most call sites already use unsigned char*
and the existing hashcmp is also declared to be unsigned char*.

[jc: this is a follow-up patch for merge-recursive.c which is
 not in "master" yet.  The original was sent-in for "next" so
 I splitted it out. ]

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-23 14:27:00 -07:00
Junio C Hamano
eed94a570e Merge branch 'master' into js/c-merge-recursive
Adjust to hold_lock_file_for_update() change on the master.
2006-08-12 18:35:14 -07:00
Johannes Schindelin
984b65707e merge-recur: do not die unnecessarily
When the cache is dirty, and we switch the index file from temporary
to final, we want to discard the cache without complaint.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-09 14:57:27 -07:00
Johannes Schindelin
8918b0c9c2 merge-recur: try to merge older merge bases first
It seems to be the only sane way to do it: when a two-head merge is
done, and the merge-base and one of the two branches agree, the
merge assumes that the other branch has something new.

If we start creating virtual commits from newer merge-bases, and go
back to older merge-bases, and then merge with newer commits again,
chances are that a patch is lost, _because_ the merge-base and the
head agree on it. Unlikely, yes, but it happened to me.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-09 14:57:22 -07:00
Johannes Schindelin
934d9a2407 merge-recur: if there is no common ancestor, fake empty one
This fixes the coolest merge ever.

[jc: with two "Oops that's not it" fixes from Johannes and Alex,
 and an obvious type mismatch fix.]

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-09 14:54:00 -07:00
Johannes Schindelin
c1964a006f merge-recur: do not setenv("GIT_INDEX_FILE")
Since there are no external calls left in merge-recur, we do not need
to set the environment variable GIT_INDEX_FILE all the time.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-09 14:49:26 -07:00
Johannes Schindelin
5b982f84ee merge-recur: do not call git-write-tree
Since merge-recur is in C, and uses libgit, it can call the relevant
functions directly, without writing the index file.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-09 14:46:47 -07:00
Johannes Schindelin
3d234d0afa merge-recursive: fix rename handling
To handle renames properly, we iterate through all file names of both
heads, the current one, and the one to be merged.

Only that there was a bug, where it was checked if the file name was present
in both heads, but the result of the check was never used. Instead, the
merge proceeded as if both heads contained that file.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-08-04 11:30:35 -07:00
Johannes Schindelin
c1f3089e4b merge-recur: virtual commits shall never be parsed
It would not make sense to parse a virtual commit, therefore set the
"parsed" flag to 1.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-07-31 15:41:12 -07:00
Johannes Schindelin
7a85b848ad merge-recur: use the unpack_trees() interface instead of exec()ing read-tree
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-07-30 23:55:49 -07:00
Johannes Schindelin
f59aac47f3 merge-recur: fix thinko in unique_path()
This could result in a nasty infinite loop, or in bogus names (it used
the strlen() of the newly allocated buffer instead of the original
buffer).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-07-30 14:23:00 -07:00
Johannes Schindelin
3058e9339f merge-recur: Explain why sha_eq() and struct stage_data cannot go
There were two TODOs to remove sha_eq() and to convert users of
struct stage_data to active_cache users, but this is not possible.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-07-27 19:39:15 -07:00
Johannes Schindelin
c1d20846f4 merge-recur: Cleanup last mixedCase variables...
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-07-27 19:39:15 -07:00
Johannes Schindelin
7b3f5daabc merge-recur: Fix compiler warning with -pedantic
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-07-27 19:39:15 -07:00
Johannes Schindelin
5d3afe05d9 merge-recur: Remove dead code
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-07-27 19:39:15 -07:00
Johannes Schindelin
bd669986f7 merge-recur: Get rid of debug code
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-07-27 19:39:15 -07:00