* [StGit PATCH 08/10] Let "stg clean" use the new transaction primitives
From: Karl Hasselström @ 2007-11-25 20:51 UTC (permalink / raw)
To: Catalin Marinas; +Cc: git, David Kågedal
In-Reply-To: <20071125203717.7823.70046.stgit@yoghurt>
Signed-off-by: Karl Hasselström <kha@treskal.com>
---
stgit/commands/clean.py | 33 +++++++--------------------------
1 files changed, 7 insertions(+), 26 deletions(-)
diff --git a/stgit/commands/clean.py b/stgit/commands/clean.py
index e2d1678..cfcc004 100644
--- a/stgit/commands/clean.py
+++ b/stgit/commands/clean.py
@@ -37,33 +37,14 @@ options = [make_option('-a', '--applied',
def _clean(stack, clean_applied, clean_unapplied):
- def deleting(pn):
- out.info('Deleting empty patch %s' % pn)
trans = transaction.StackTransaction(stack, 'clean')
- if clean_unapplied:
- trans.unapplied = []
- for pn in stack.patchorder.unapplied:
- p = stack.patches.get(pn)
- if p.commit.data.is_empty():
- trans.patches[pn] = None
- deleting(pn)
- else:
- trans.unapplied.append(pn)
- if clean_applied:
- trans.applied = []
- parent = stack.base
- for pn in stack.patchorder.applied:
- p = stack.patches.get(pn)
- if p.commit.data.is_empty():
- trans.patches[pn] = None
- deleting(pn)
- else:
- if parent != p.commit.data.parent:
- parent = trans.patches[pn] = stack.repository.commit(
- p.commit.data.set_parent(parent))
- else:
- parent = p.commit
- trans.applied.append(pn)
+ def del_patch(pn):
+ if pn in stack.patchorder.applied:
+ return clean_applied and trans.patches[pn].data.is_empty()
+ elif pn in stack.patchorder.unapplied:
+ return clean_unapplied and trans.patches[pn].data.is_empty()
+ for pn in trans.delete_patches(del_patch):
+ trans.push_patch(pn)
trans.run()
def func(parser, options, args):
^ permalink raw reply related
* [StGit PATCH 05/10] Add "stg coalesce"
From: Karl Hasselström @ 2007-11-25 20:51 UTC (permalink / raw)
To: Catalin Marinas; +Cc: git, David Kågedal
In-Reply-To: <20071125203717.7823.70046.stgit@yoghurt>
It coalesces two or more consecutive applied patches, with no need to
touch index/worktree, and no possibiliy of conflicts.
Future improvements could relax the "consecutive" and "applied"
restrictions, by building a new chain of commits just like "stg push"
will do once it's been converted to the new infrastructure.
Signed-off-by: Karl Hasselström <kha@treskal.com>
---
contrib/stgit-completion.bash | 2 +
stgit/commands/coalesce.py | 84 +++++++++++++++++++++++++++++++++++++++++
stgit/main.py | 2 +
stgit/utils.py | 11 +++++
t/t2600-coalesce.sh | 31 +++++++++++++++
5 files changed, 130 insertions(+), 0 deletions(-)
create mode 100644 stgit/commands/coalesce.py
create mode 100755 t/t2600-coalesce.sh
diff --git a/contrib/stgit-completion.bash b/contrib/stgit-completion.bash
index b3b23d4..b02eb64 100644
--- a/contrib/stgit-completion.bash
+++ b/contrib/stgit-completion.bash
@@ -18,6 +18,7 @@ _stg_commands="
diff
clean
clone
+ coalesce
commit
cp
edit
@@ -238,6 +239,7 @@ _stg ()
# repository commands
id) _stg_patches $command _all_patches ;;
# stack commands
+ coalesce) _stg_patches $command _applied_patches ;;
float) _stg_patches $command _all_patches ;;
goto) _stg_patches $command _all_other_patches ;;
hide) _stg_patches $command _unapplied_patches ;;
diff --git a/stgit/commands/coalesce.py b/stgit/commands/coalesce.py
new file mode 100644
index 0000000..c4c1cf8
--- /dev/null
+++ b/stgit/commands/coalesce.py
@@ -0,0 +1,84 @@
+# -*- coding: utf-8 -*-
+
+__copyright__ = """
+Copyright (C) 2007, Karl Hasselström <kha@treskal.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+"""
+
+from optparse import make_option
+from stgit.out import *
+from stgit import utils
+from stgit.commands import common
+from stgit.lib import git, transaction
+
+help = 'coalesce two or more patches into one'
+usage = """%prog [options] <patches>
+
+Coalesce two or more patches, creating one big patch that contains all
+their changes. The patches must all be applied, and must be
+consecutive."""
+
+directory = common.DirectoryHasRepositoryLib()
+options = [make_option('-n', '--name', help = 'name of coalesced patch'),
+ make_option('-m', '--message',
+ help = 'commit message of coalesced patch')]
+
+def _coalesce(stack, name, msg, patches):
+ applied = stack.patchorder.applied
+
+ # Make sure the patches are consecutive.
+ applied_ix = dict((applied[i], i) for i in xrange(len(applied)))
+ ixes = list(sorted(applied_ix[p] for p in patches))
+ i0, i1 = ixes[0], ixes[-1]
+ if i1 - i0 + 1 != len(patches):
+ raise common.CmdException('The patches must be consecutive')
+
+ # Make a commit for the coalesced patch.
+ def bad_name(pn):
+ return pn not in patches and stack.patches.exists(pn)
+ if name and bad_name(name):
+ raise common.CmdException('Patch name "%s" already taken')
+ ps = [stack.patches.get(pn) for pn in applied[i0:i1+1]]
+ if msg == None:
+ msg = '\n\n'.join('%s\n\n%s' % (p.name.ljust(70, '-'),
+ p.commit.data.message)
+ for p in ps)
+ msg = utils.edit_string(msg, '.stgit-coalesce.txt').strip()
+ if not name:
+ name = utils.make_patch_name(msg, bad_name)
+ cd = git.Commitdata(tree = ps[-1].commit.data.tree,
+ parents = ps[0].commit.data.parents, message = msg)
+
+ # Rewrite refs.
+ trans = transaction.StackTransaction(stack, 'stg coalesce')
+ for pn in applied[i0:i1+1]:
+ trans.patches[pn] = None
+ parent = trans.patches[name] = stack.repository.commit(cd)
+ trans.applied = applied[:i0]
+ trans.applied.append(name)
+ for pn in applied[i1+1:]:
+ p = stack.patches.get(pn)
+ parent = trans.patches[pn] = stack.repository.commit(
+ p.commit.data.set_parent(parent))
+ trans.applied.append(pn)
+ trans.run()
+
+def func(parser, options, args):
+ stack = directory.repository.current_stack
+ applied = set(stack.patchorder.applied)
+ patches = set(common.parse_patches(args, list(stack.patchorder.applied)))
+ if len(patches) < 2:
+ raise common.CmdException('Need at least two patches')
+ _coalesce(stack, options.name, options.message, patches)
diff --git a/stgit/main.py b/stgit/main.py
index deaac91..384803b 100644
--- a/stgit/main.py
+++ b/stgit/main.py
@@ -64,6 +64,7 @@ commands = Commands({
'diff': 'diff',
'clean': 'clean',
'clone': 'clone',
+ 'coalesce': 'coalesce',
'commit': 'commit',
'edit': 'edit',
'export': 'export',
@@ -108,6 +109,7 @@ stackcommands = (
'applied',
'branch',
'clean',
+ 'coalesce',
'commit',
'float',
'goto',
diff --git a/stgit/utils.py b/stgit/utils.py
index b3f6232..688276c 100644
--- a/stgit/utils.py
+++ b/stgit/utils.py
@@ -189,6 +189,17 @@ def call_editor(filename):
raise EditorException, 'editor failed, exit code: %d' % err
out.done()
+def edit_string(s, filename):
+ f = file(filename, 'w')
+ f.write(s)
+ f.close()
+ call_editor(filename)
+ f = file(filename)
+ s = f.read()
+ f.close()
+ os.remove(filename)
+ return s
+
def patch_name_from_msg(msg):
"""Return a string to be used as a patch name. This is generated
from the top line of the string passed as argument."""
diff --git a/t/t2600-coalesce.sh b/t/t2600-coalesce.sh
new file mode 100755
index 0000000..f13a309
--- /dev/null
+++ b/t/t2600-coalesce.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+test_description='Run "stg coalesce"'
+
+. ./test-lib.sh
+
+test_expect_success 'Initialize StGit stack' '
+ stg init &&
+ for i in 0 1 2 3; do
+ stg new p$i -m "foo $i" &&
+ echo "foo $i" >> foo.txt &&
+ git add foo.txt &&
+ stg refresh
+ done
+'
+
+test_expect_success 'Coalesce some patches' '
+ [ "$(echo $(stg applied))" = "p0 p1 p2 p3" ] &&
+ [ "$(echo $(stg unapplied))" = "" ] &&
+ stg coalesce --name=q0 --message="wee woo" p1 p2 &&
+ [ "$(echo $(stg applied))" = "p0 q0 p3" ] &&
+ [ "$(echo $(stg unapplied))" = "" ]
+'
+
+test_expect_success 'Coalesce at stack top' '
+ stg coalesce --name=q1 --message="wee woo wham" q0 p3 &&
+ [ "$(echo $(stg applied))" = "p0 q1" ] &&
+ [ "$(echo $(stg unapplied))" = "" ]
+'
+
+test_done
^ permalink raw reply related
* [StGit PATCH 09/10] Let "stg goto" use the new infrastructure
From: Karl Hasselström @ 2007-11-25 20:51 UTC (permalink / raw)
To: Catalin Marinas; +Cc: git, David Kågedal
In-Reply-To: <20071125203717.7823.70046.stgit@yoghurt>
In the process, it loses the --keep option, since the new
infrastructure always keeps local changes (and aborts cleanly if they
are in the way).
Signed-off-by: Karl Hasselström <kha@treskal.com>
---
stgit/commands/clean.py | 2 +-
stgit/commands/goto.py | 52 ++++++++++++++++-------------------------------
2 files changed, 19 insertions(+), 35 deletions(-)
diff --git a/stgit/commands/clean.py b/stgit/commands/clean.py
index cfcc004..55ab858 100644
--- a/stgit/commands/clean.py
+++ b/stgit/commands/clean.py
@@ -37,7 +37,7 @@ options = [make_option('-a', '--applied',
def _clean(stack, clean_applied, clean_unapplied):
- trans = transaction.StackTransaction(stack, 'clean')
+ trans = transaction.StackTransaction(stack, 'stg clean')
def del_patch(pn):
if pn in stack.patchorder.applied:
return clean_applied and trans.patches[pn].data.is_empty()
diff --git a/stgit/commands/goto.py b/stgit/commands/goto.py
index 84b840b..3ea69dd 100644
--- a/stgit/commands/goto.py
+++ b/stgit/commands/goto.py
@@ -15,13 +15,9 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
-import sys, os
from optparse import OptionParser, make_option
-
-from stgit.commands.common import *
-from stgit.utils import *
-from stgit import stack, git
-
+from stgit.commands import common
+from stgit.lib import transaction
help = 'push or pop patches to the given one'
usage = """%prog [options] <name>
@@ -30,38 +26,26 @@ Push/pop patches to/from the stack until the one given on the command
line becomes current. There is no '--undo' option for 'goto'. Use the
'push --undo' command for this."""
-directory = DirectoryGotoToplevel()
-options = [make_option('-k', '--keep',
- help = 'keep the local changes when popping patches',
- action = 'store_true')]
-
+directory = common.DirectoryHasRepositoryLib()
+options = []
def func(parser, options, args):
- """Pushes the given patch or all onto the series
- """
if len(args) != 1:
parser.error('incorrect number of arguments')
-
- check_conflicts()
- check_head_top_equal(crt_series)
-
- if not options.keep:
- check_local_changes()
-
- applied = crt_series.get_applied()
- unapplied = crt_series.get_unapplied()
patch = args[0]
- if patch in applied:
- applied.reverse()
- patches = applied[:applied.index(patch)]
- pop_patches(crt_series, patches, options.keep)
- elif patch in unapplied:
- if options.keep:
- raise CmdException, 'Cannot use --keep with patch pushing'
- patches = unapplied[:unapplied.index(patch)+1]
- push_patches(crt_series, patches)
+ stack = directory.repository.current_stack
+ iw = stack.repository.default_iw()
+ trans = transaction.StackTransaction(stack, 'stg goto')
+ if patch in trans.applied:
+ to_pop = set(trans.applied[trans.applied.index(patch)+1:])
+ assert not trans.pop_patches(lambda pn: pn in to_pop)
+ elif patch in trans.unapplied:
+ try:
+ for pn in trans.unapplied[:trans.unapplied.index(patch)+1]:
+ trans.push_patch(pn, iw)
+ except transaction.TransactionHalted:
+ pass
else:
- raise CmdException, 'Patch "%s" does not exist' % patch
-
- print_crt_patch(crt_series)
+ raise CmdException('Patch "%s" does not exist' % patch)
+ trans.run(iw)
^ permalink raw reply related
* [StGit PATCH 10/10] Convert "stg uncommit" to the new infrastructure
From: Karl Hasselström @ 2007-11-25 20:51 UTC (permalink / raw)
To: Catalin Marinas; +Cc: git, David Kågedal
In-Reply-To: <20071125203717.7823.70046.stgit@yoghurt>
Signed-off-by: Karl Hasselström <kha@treskal.com>
---
stgit/commands/uncommit.py | 79 +++++++++++++++++++-------------------------
1 files changed, 34 insertions(+), 45 deletions(-)
diff --git a/stgit/commands/uncommit.py b/stgit/commands/uncommit.py
index ba3448f..8422952 100644
--- a/stgit/commands/uncommit.py
+++ b/stgit/commands/uncommit.py
@@ -17,13 +17,11 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
-import sys, os
-from optparse import OptionParser, make_option
-
-from stgit.commands.common import *
-from stgit.utils import *
+from optparse import make_option
+from stgit.commands import common
+from stgit.lib import transaction
from stgit.out import *
-from stgit import stack, git
+from stgit import utils
help = 'turn regular GIT commits into StGIT patches'
usage = """%prog [<patchnames>] | -n NUM [<prefix>]] | -t <committish> [-x]
@@ -48,7 +46,7 @@ given commit should be uncommitted.
Only commits with exactly one parent can be uncommitted; in other
words, you can't uncommit a merge."""
-directory = DirectoryGotoToplevel()
+directory = common.DirectoryHasRepositoryLib()
options = [make_option('-n', '--number', type = 'int',
help = 'uncommit the specified number of commits'),
make_option('-t', '--to',
@@ -60,19 +58,18 @@ options = [make_option('-n', '--number', type = 'int',
def func(parser, options, args):
"""Uncommit a number of patches.
"""
+ stack = directory.repository.current_stack
if options.to:
if options.number:
parser.error('cannot give both --to and --number')
if len(args) != 0:
parser.error('cannot specify patch name with --to')
patch_nr = patchnames = None
- to_commit = git_id(crt_series, options.to)
+ to_commit = stack.repository.rev_parse(options.to)
elif options.number:
if options.number <= 0:
parser.error('invalid value passed to --number')
-
patch_nr = options.number
-
if len(args) == 0:
patchnames = None
elif len(args) == 1:
@@ -88,53 +85,45 @@ def func(parser, options, args):
patchnames = args
patch_nr = len(patchnames)
- if crt_series.get_protected():
- raise CmdException, \
- 'This branch is protected. Uncommit is not permitted'
-
- def get_commit(commit_id):
- commit = git.Commit(commit_id)
- try:
- parent, = commit.get_parents()
- except ValueError:
- raise CmdException('Commit %s does not have exactly one parent'
- % commit_id)
- return (commit, commit_id, parent)
-
commits = []
- next_commit = crt_series.get_base()
+ next_commit = stack.base
if patch_nr:
out.start('Uncommitting %d patches' % patch_nr)
for i in xrange(patch_nr):
- commit, commit_id, parent = get_commit(next_commit)
- commits.append((commit, commit_id, parent))
- next_commit = parent
+ commits.append(next_commit)
+ next_commit = next_commit.data.parent
else:
if options.exclusive:
out.start('Uncommitting to %s (exclusive)' % to_commit)
else:
out.start('Uncommitting to %s' % to_commit)
while True:
- commit, commit_id, parent = get_commit(next_commit)
- if commit_id == to_commit:
+ if next_commit == to_commit:
if not options.exclusive:
- commits.append((commit, commit_id, parent))
+ commits.append(next_commit)
break
- commits.append((commit, commit_id, parent))
- next_commit = parent
+ commits.append(next_commit)
+ next_commit = next_commit.data.parent
patch_nr = len(commits)
- for (commit, commit_id, parent), patchname in \
- zip(commits, patchnames or [None for i in xrange(len(commits))]):
- author_name, author_email, author_date = \
- name_email_date(commit.get_author())
- crt_series.new_patch(patchname,
- can_edit = False, before_existing = True,
- commit = False,
- top = commit_id, bottom = parent,
- message = commit.get_log(),
- author_name = author_name,
- author_email = author_email,
- author_date = author_date)
-
+ taken_names = set(stack.patchorder.applied + stack.patchorder.unapplied)
+ if patchnames:
+ for pn in patchnames:
+ if pn in taken_names:
+ raise common.CmdException('Patch name "%s" already taken' % pn)
+ taken_names.add(pn)
+ else:
+ patchnames = []
+ for c in reversed(commits):
+ pn = utils.make_patch_name(c.data.message,
+ lambda pn: pn in taken_names)
+ patchnames.append(pn)
+ taken_names.add(pn)
+ patchnames.reverse()
+
+ trans = transaction.StackTransaction(stack, 'stg uncommit')
+ for commit, pn in zip(commits, patchnames):
+ trans.patches[pn] = commit
+ trans.applied = list(reversed(patchnames)) + trans.applied
+ trans.run()
out.done()
^ permalink raw reply related
* Re: What's cooking in git.git (topics)
From: J. Bruce Fields @ 2007-11-25 20:53 UTC (permalink / raw)
To: Jakub Narebski; +Cc: git
In-Reply-To: <ficmbr$s87$1@ger.gmane.org>
On Sun, Nov 25, 2007 at 09:36:14PM +0100, Jakub Narebski wrote:
> Junio C Hamano wrote:
>
> > [Actively cooking]
> >
> > * jc/spht (Sat Nov 24 11:57:41 2007 -0800) 6 commits
> > + core.whitespace: documentation updates.
> > + builtin-apply: teach whitespace_rules
> > + builtin-apply: rename "whitespace" variables and fix styles
> > + core.whitespace: add test for diff whitespace error highlighting
> > + git-diff: complain about >=8 consecutive spaces in initial indent
> > + War on whitespace: first, a bit of retreat.
> >
> > Now apply also knows about the customizable definition of what
> > whitespace breakages are, and I was reasonably happy. But Bruce kicked
> > it back from "scheduled to merge" to "still cooking" status, reminding
> > that we would want to have this not a tree-wide configuration but
> > per-path attribute. And I agree with him.
>
> Currently apply.whitespace is per repository - would this be changed
> as well,
There's a difference between the choice of preferred whitespace style
and the choice of action to take when encountering "bad" whitespace.
The former is (I think) obviously a property of the project (or perhaps
of individual paths within the project). The latter may depend on what
you're doing with it at any given moment--for example, if I'm applying
patches to submit, I generally want to fix whitespace, but if I'm just
examining someone else's patches temporarily then I might want to import
them quickly without fixing up everything.
So, no, I don't think there should be a .gitattribute equivalent to
apply.whitespace.
--b.
> i.e. would it be moved to gitattributes together with custom
> diff drivers (or at least custom funcnames), custom merge drivers,
> making it per-project (if put under version control) and per-path?
>
>
> By the way, i18n.commitEncoding is per repository, and used to affect
> repository; not so with the "encoding" header in commit object.
>
> --
> Jakub Narebski
> Warsaw, Poland
> ShadeHawk on #git
>
>
> -
> 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
* [RFC] best way to show diff of commit
From: Pierre Habouzit @ 2007-11-25 21:18 UTC (permalink / raw)
To: Git ML
[-- Attachment #1: Type: text/plain, Size: 1281 bytes --]
Hi there,
There is specific script I run in my vim with git, that tries to show
from the 'status' git commit shows in the buffer which list of files has
changed, and builds a diff from it quite clumsily[0].
I wonder how hard it would be for git commit to "stash" the current
commit being sent somewhere editors would be able to have a look at (an
alternate index is probably fine). Note that maybe I'm stupid and
overlooked that such a thing already exists. I'd like to have it in two
flavors: normal and amend mode. normal mode would show what the
resulting commit diff looks like, and the amend mode only shows the
incrementall diff the amend adds to the previous commit.
My question is: what do you think is the best way to do that, and
where ?
[0] the issue with this approach is that it's completely broken in
amending mode (does not shows the proper thing), and the generated
diffs aren't excellent, because as an editor plugin, it's hard to
treat renames and copies easily, so I generate really really nasty
diffs in that case too.
--
·O· Pierre Habouzit
··O madcoder@debian.org
OOO http://www.madism.org
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [RFC] best way to show diff of commit
From: J. Bruce Fields @ 2007-11-25 21:27 UTC (permalink / raw)
To: Pierre Habouzit, Git ML
In-Reply-To: <20071125211831.GA21121@artemis.corp>
On Sun, Nov 25, 2007 at 10:18:31PM +0100, Pierre Habouzit wrote:
> There is specific script I run in my vim with git, that tries to show
> from the 'status' git commit shows in the buffer which list of files has
> changed, and builds a diff from it quite clumsily[0].
>
> I wonder how hard it would be for git commit to "stash" the current
> commit being sent somewhere editors would be able to have a look at (an
> alternate index is probably fine). Note that maybe I'm stupid and
> overlooked that such a thing already exists. I'd like to have it in two
> flavors: normal and amend mode. normal mode would show what the
> resulting commit diff looks like, and the amend mode only shows the
> incrementall diff the amend adds to the previous commit.
>
> My question is: what do you think is the best way to do that, and
> where ?
Have you checked whether "git-commit -v" already does what you want?
--b.
^ permalink raw reply
* [Resend Trivial PATCH] For the sake of correctness, fix file descriptor leak.
From: André Goddard Rosa @ 2007-11-25 21:37 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git Mailing List
In-Reply-To: <b8bf37780711211659v4fbd5936t29d0a0a2ff84f4b@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1077 bytes --]
Hi, all!
Plug a file descriptor leak.
From 9fba346aca7470633ee46848013051248493896c Mon Sep 17 00:00:00 2001
From: Andre Goddard Rosa <andre.goddard@gmail.com>
Date: Tue, 27 Nov 2007 10:16:22 -0200
Subject: [PATCH] For the sake of correctness, fix file descriptor leak.
Signed-off-by: Andre Goddard Rosa <andre.goddard@gmail.com>
---
builtin-rerere.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/builtin-rerere.c b/builtin-rerere.c
index 7449323..31766be 100644
--- a/builtin-rerere.c
+++ b/builtin-rerere.c
@@ -275,8 +275,10 @@ static int copy_file(const char *src, const char *dest)
if (!(in = fopen(src, "r")))
return error("Could not open %s", src);
- if (!(out = fopen(dest, "w")))
+ if (!(out = fopen(dest, "w"))) {
+ fclose(in);
return error("Could not open %s", dest);
+ }
while ((count = fread(buffer, 1, sizeof(buffer), in)))
fwrite(buffer, 1, count, out);
fclose(in);
--
1.5.3.6.861.gd794-dirty
--
[]s,
André Goddard
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0002-For-the-sake-of-correctness-fix-file-descriptor-le.patch --]
[-- Type: text/x-patch; name=0002-For-the-sake-of-correctness-fix-file-descriptor-le.patch, Size: 921 bytes --]
From 9fba346aca7470633ee46848013051248493896c Mon Sep 17 00:00:00 2001
From: Andre Goddard Rosa <andre.goddard@gmail.com>
Date: Tue, 27 Nov 2007 10:16:22 -0200
Subject: [PATCH] For the sake of correctness, fix file descriptor leak.
Signed-off-by: Andre Goddard Rosa <andre.goddard@gmail.com>
---
builtin-rerere.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/builtin-rerere.c b/builtin-rerere.c
index 7449323..31766be 100644
--- a/builtin-rerere.c
+++ b/builtin-rerere.c
@@ -275,8 +275,10 @@ static int copy_file(const char *src, const char *dest)
if (!(in = fopen(src, "r")))
return error("Could not open %s", src);
- if (!(out = fopen(dest, "w")))
+ if (!(out = fopen(dest, "w"))) {
+ fclose(in);
return error("Could not open %s", dest);
+ }
while ((count = fread(buffer, 1, sizeof(buffer), in)))
fwrite(buffer, 1, count, out);
fclose(in);
--
1.5.3.6.861.gd794-dirty
^ permalink raw reply related
* [PATCH] Add 'git fast-export', the sister of 'git fast-import'
From: Johannes Schindelin @ 2007-11-25 21:37 UTC (permalink / raw)
To: git, gitster
[-- Attachment #1: Type: TEXT/PLAIN, Size: 19296 bytes --]
This program dumps (parts of) a git repository in the format that
fast-import understands.
For clarity's sake, it does not use the 'inline' method of specifying
blobs in the commits, but builds the blobs before building the commits.
Since signed tags' signatures will not necessarily be valid (think
transformations after the export, or excluding revisions, changing
the history), there are 4 modes to handle them: abort (default),
ignore, warn and strip. The latter just turns the tags into
unsigned ones.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
This should be feature complete AFAICT.
.gitignore | 1 +
Documentation/git-fast-export.txt | 83 ++++++++
Makefile | 1 +
builtin-fast-export.c | 407 +++++++++++++++++++++++++++++++++++++
builtin.h | 1 +
git.c | 1 +
t/t9301-fast-export.sh | 124 +++++++++++
7 files changed, 618 insertions(+), 0 deletions(-)
create mode 100644 Documentation/git-fast-export.txt
create mode 100755 builtin-fast-export.c
create mode 100755 t/t9301-fast-export.sh
diff --git a/.gitignore b/.gitignore
index 6564618..8694d02 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,6 +35,7 @@ git-diff-files
git-diff-index
git-diff-tree
git-describe
+git-fast-export
git-fast-import
git-fetch
git-fetch--tool
diff --git a/Documentation/git-fast-export.txt b/Documentation/git-fast-export.txt
new file mode 100644
index 0000000..073ff7f
--- /dev/null
+++ b/Documentation/git-fast-export.txt
@@ -0,0 +1,83 @@
+git-fast-export(1)
+==================
+
+NAME
+----
+git-fast-export - Git data exporter
+
+
+SYNOPSIS
+--------
+'git-fast-export [options]' | 'git-fast-import'
+
+DESCRIPTION
+-----------
+This program dumps the given revisions in a form suitable to be piped
+into gitlink:git-fast-import[1].
+
+You can use it as a human readable bundle replacement (see
+gitlink:git-bundle[1]), or as a kind of an interactive
+gitlink:git-filter-branch[1].
+
+
+OPTIONS
+-------
+--progress=<n>::
+ Insert 'progress' statements every <n> objects, to be shown by
+ gitlink:git-fast-import[1] during import.
+
+--signed-tags=(ignore|warn|strip|abort)::
+ Specify how to handle signed tags. Since any transformation
+ after the export can change the tag names (which can also happen
+ when excluding revisions) the signatures will not match.
++
+When asking to 'abort' (which is the default), this program will die
+when encountering a signed tag. With 'strip', the tags will be made
+unsigned, with 'ignore', they will be silently ignored (i.e. not exported)
+and with 'warn', they will be exported, but you will see a warning.
+
+
+EXAMPLES
+--------
+
+-------------------------------------------------------------------
+$ git fast-export --all | (cd /empty/repository && git fast-import)
+-------------------------------------------------------------------
+
+This will export the whole repository and import it into the existing
+empty repository. Except for reencoding commits that are not in
+UTF-8, it would be a one-to-one mirror.
+
+-----------------------------------------------------
+$ git fast-export master~5..master |
+ sed "s|refs/heads/master|refs/heads/other|" |
+ git fast-import
+-----------------------------------------------------
+
+This makes a new branch called 'other' from 'master~5..master'
+(i.e. if 'master' has linear history, it will take the last 5 commits).
+
+Note that this assumes that none of the blobs and commit messages
+referenced by that revision range contains the string
+'refs/heads/master'.
+
+
+Limitations
+-----------
+
+Since gitlink:git-fast-import[1] cannot tag trees, you will not be
+able to export the linux-2.6.git repository completely, as it contains
+a tag referencing a tree instead of a commit.
+
+
+Author
+------
+Written by Johannes E. Schindelin <johannes.schindelin@gmx.de>.
+
+Documentation
+--------------
+Documentation by Johannes E. Schindelin <johannes.schindelin@gmx.de>.
+
+GIT
+---
+Part of the gitlink:git[7] suite
diff --git a/Makefile b/Makefile
index 0719fb8..ebd12ed 100644
--- a/Makefile
+++ b/Makefile
@@ -337,6 +337,7 @@ BUILTIN_OBJS = \
builtin-diff-files.o \
builtin-diff-index.o \
builtin-diff-tree.o \
+ builtin-fast-export.o \
builtin-fetch.o \
builtin-fetch-pack.o \
builtin-fetch--tool.o \
diff --git a/builtin-fast-export.c b/builtin-fast-export.c
new file mode 100755
index 0000000..48d0c54
--- /dev/null
+++ b/builtin-fast-export.c
@@ -0,0 +1,407 @@
+/*
+ * "git fast-export" builtin command
+ *
+ * Copyright (C) 2007 Johannes E. Schindelin
+ */
+#include "builtin.h"
+#include "cache.h"
+#include "commit.h"
+#include "object.h"
+#include "tag.h"
+#include "diff.h"
+#include "diffcore.h"
+#include "log-tree.h"
+#include "revision.h"
+#include "decorate.h"
+#include "path-list.h"
+#include "utf8.h"
+#include "parse-options.h"
+
+/*
+ * TODO:
+ * - tags (--signed-tags=(ignore|warn|strip|abort)
+ */
+
+static const char *fast_export_usage[] = {
+ "git-fast-export [rev-list-opts]",
+ NULL
+};
+
+static int progress;
+static enum { IGNORE, WARN, STRIP, ABORT } signed_tag_mode = ABORT;
+
+static int parse_opt_signed_tag_mode(const struct option *opt,
+ const char *arg, int unset)
+{
+ if (unset || !strcmp(arg, "abort"))
+ signed_tag_mode = ABORT;
+ else if (!strcmp(arg, "ignore"))
+ signed_tag_mode = IGNORE;
+ else if (!strcmp(arg, "warn"))
+ signed_tag_mode = WARN;
+ else if (!strcmp(arg, "strip"))
+ signed_tag_mode = STRIP;
+ else
+ return error("Unknown signed-tag mode: %s", arg);
+ return 0;
+}
+
+static struct decoration idnums;
+static uint32_t last_idnum;
+
+static int has_unshown_parent(struct commit *commit)
+{
+ struct commit_list *parent;
+
+ for (parent = commit->parents; parent; parent = parent->next)
+ if (!(parent->item->object.flags & SHOWN) &&
+ !(parent->item->object.flags & UNINTERESTING))
+ return 1;
+ return 0;
+}
+
+/* Since intptr_t is C99, we do not use it here */
+static void mark_object(struct object *object)
+{
+ last_idnum++;
+ add_decoration(&idnums, object, (void *)last_idnum);
+}
+
+static int get_object_mark(struct object *object)
+{
+ return (int)lookup_decoration(&idnums, object);
+}
+
+static void show_progress(void)
+{
+ static int counter = 0;
+ if (!progress)
+ return;
+ if ((++counter % progress) == 0)
+ printf("progress %d objects\n", counter);
+}
+
+static void handle_object(const unsigned char *sha1)
+{
+ unsigned long size;
+ enum object_type type;
+ char *buf;
+ struct object *object;
+
+ if (is_null_sha1(sha1))
+ return;
+
+ object = parse_object(sha1);
+ if (!object)
+ die ("Could not read blob %s", sha1_to_hex(sha1));
+
+ if (object->flags & SHOWN)
+ return;
+
+ buf = read_sha1_file(sha1, &type, &size);
+ if (!buf)
+ die ("Could not read blob %s", sha1_to_hex(sha1));
+
+ mark_object(object);
+
+ printf("blob\nmark :%d\ndata %lu\n", last_idnum, size);
+ if (fwrite(buf, size, 1, stdout) != 1)
+ die ("Could not write blob %s", sha1_to_hex(sha1));
+ printf("\n");
+
+ show_progress();
+
+ object->flags |= SHOWN;
+ free(buf);
+}
+
+static void show_filemodify(struct diff_queue_struct *q,
+ struct diff_options *options, void *data)
+{
+ int i;
+ for (i = 0; i < q->nr; i++) {
+ struct diff_filespec *spec = q->queue[i]->two;
+ if (is_null_sha1(spec->sha1))
+ printf("D %s\n", spec->path);
+ else {
+ struct object *object = lookup_object(spec->sha1);
+ printf("M 0%06o :%d %s\n", spec->mode,
+ get_object_mark(object), spec->path);
+ }
+ }
+}
+
+static const char *find_encoding(const char *begin, const char *end)
+{
+ const char *needle = "\nencoding ";
+ char *bol, *eol;
+
+ bol = memmem(begin, end ? end - begin : strlen(begin),
+ needle, strlen(needle));
+ if (!bol)
+ return git_commit_encoding;
+ bol += strlen(needle);
+ eol = strchrnul(bol, '\n');
+ *eol = '\0';
+ return bol;
+}
+
+static void handle_commit(struct commit *commit, struct rev_info *rev)
+{
+ int saved_output_format = rev->diffopt.output_format;
+ const char *author, *author_end, *committer, *committer_end;
+ const char *encoding, *message;
+ char *reencoded = NULL;
+ struct commit_list *p;
+ int i;
+
+ rev->diffopt.output_format = DIFF_FORMAT_CALLBACK;
+
+ parse_commit(commit);
+ author = strstr(commit->buffer, "\nauthor ");
+ if (!author)
+ die ("Could not find author in commit %s",
+ sha1_to_hex(commit->object.sha1));
+ author++;
+ author_end = strchrnul(author, '\n');
+ committer = strstr(author_end, "\ncommitter ");
+ if (!committer)
+ die ("Could not find committer in commit %s",
+ sha1_to_hex(commit->object.sha1));
+ committer++;
+ committer_end = strchrnul(committer, '\n');
+ message = strstr(committer_end, "\n\n");
+ encoding = find_encoding(committer_end, message);
+ if (message)
+ message += 2;
+
+ if (commit->parents) {
+ parse_commit(commit->parents->item);
+ diff_tree_sha1(commit->parents->item->tree->object.sha1,
+ commit->tree->object.sha1, "", &rev->diffopt);
+ }
+ else
+ diff_root_tree_sha1(commit->tree->object.sha1,
+ "", &rev->diffopt);
+
+ for (i = 0; i < diff_queued_diff.nr; i++)
+ handle_object(diff_queued_diff.queue[i]->two->sha1);
+
+ mark_object(&commit->object);
+ if (!is_encoding_utf8(encoding))
+ reencoded = reencode_string(message, "UTF-8", encoding);
+ printf("commit %s\nmark :%d\n%.*s\n%.*s\ndata %u\n%s",
+ (const char *)commit->util, last_idnum,
+ author_end - author, author,
+ committer_end - committer, committer,
+ reencoded ? strlen(reencoded) : message ? strlen(message) : 0,
+ reencoded ? reencoded : message ? message : "");
+ if (reencoded)
+ free(reencoded);
+
+ for (i = 0, p = commit->parents; p; p = p->next) {
+ int mark = get_object_mark(&p->item->object);
+ if (!mark)
+ continue;
+ if (i == 0)
+ printf("from :%d\n", mark);
+ else if (i == 1)
+ printf("merge :%d", mark);
+ else
+ printf(" :%d", mark);
+ i++;
+ }
+ if (i > 1)
+ printf("\n");
+
+ log_tree_diff_flush(rev);
+ rev->diffopt.output_format = saved_output_format;
+
+ printf("\n");
+
+ show_progress();
+}
+
+static void handle_tail(struct object_array *commits, struct rev_info *revs)
+{
+ struct commit *commit;
+ while (commits->nr) {
+ commit = (struct commit *)commits->objects[commits->nr - 1].item;
+ if (has_unshown_parent(commit))
+ return;
+ handle_commit(commit, revs);
+ commits->nr--;
+ }
+}
+
+static void handle_tag(const char *name, struct tag *tag)
+{
+ unsigned long size;
+ enum object_type type;
+ char *buf;
+ const char *tagger, *tagger_end, *message;
+ size_t message_size = 0;
+
+ buf = read_sha1_file(tag->object.sha1, &type, &size);
+ if (!buf)
+ die ("Could not read tag %s", sha1_to_hex(tag->object.sha1));
+ message = memmem(buf, size, "\n\n", 2);
+ if (message) {
+ message += 2;
+ message_size = strlen(message);
+ }
+ tagger = memmem(buf, message ? message - buf : size, "\ntagger ", 8);
+ if (!tagger)
+ die ("No tagger for tag %s", sha1_to_hex(tag->object.sha1));
+ tagger++;
+ tagger_end = strchrnul(tagger, '\n');
+
+ /* handle signed tags */
+ if (message) {
+ const char *signature = strstr(message,
+ "\n-----BEGIN PGP SIGNATURE-----\n");
+ if (signature)
+ switch(signed_tag_mode) {
+ case ABORT:
+ die ("Encountered signed tag %s; use "
+ "--signed-tag=<mode> to handle it.",
+ sha1_to_hex(tag->object.sha1));
+ case WARN:
+ warning ("Exporting signed tag %s",
+ sha1_to_hex(tag->object.sha1));
+ /* fallthru */
+ case IGNORE:
+ break;
+ case STRIP:
+ message_size = signature + 1 - message;
+ break;
+ }
+ }
+
+ if (!prefixcmp(name, "refs/tags/"))
+ name += 10;
+ printf("tag %s\nfrom :%d\n%.*s\ndata %d\n%.*s\n",
+ name, get_object_mark(tag->tagged),
+ tagger_end - tagger, tagger,
+ message_size, message_size, message ? message : "");
+}
+
+static void get_tags_and_duplicates(struct object_array *pending,
+ struct path_list *extra_refs)
+{
+ struct commit *commit;
+ struct tag *tag;
+ int i;
+
+ for (i = 0; i < pending->nr; i++) {
+ struct object_array_entry *e = pending->objects + i;
+ unsigned char sha1[20];
+ char *full_name;
+
+ if (dwim_ref(e->name, strlen(e->name), sha1, &full_name) != 1)
+ continue;
+
+ switch (e->item->type) {
+ case OBJ_COMMIT:
+ commit = (struct commit *)e->item;
+ break;
+ case OBJ_TAG:
+ tag = (struct tag *)e->item;
+ while (tag && tag->object.type == OBJ_TAG) {
+ path_list_insert(full_name, extra_refs)->util
+ = tag;
+ tag = (struct tag *)tag->tagged;
+ }
+ if (!tag)
+ die ("Tag %s points nowhere?", e->name);
+ switch(tag->object.type) {
+ case OBJ_COMMIT:
+ commit = (struct commit *)tag;
+ break;
+ case OBJ_BLOB:
+ handle_object(tag->object.sha1);
+ continue;
+ }
+ break;
+ default:
+ die ("Unexpected object of type %s",
+ typename(e->item->type));
+ }
+ if (commit->util)
+ /* more than one name for the same object */
+ path_list_insert(full_name, extra_refs)->util = commit;
+ else
+ commit->util = full_name;
+ }
+}
+
+static void handle_tags_and_duplicates(struct path_list *extra_refs)
+{
+ struct commit *commit;
+ int i;
+
+ for (i = extra_refs->nr - 1; i >= 0; i--) {
+ const char *name = extra_refs->items[i].path;
+ struct object *object = extra_refs->items[i].util;
+ switch (object->type) {
+ case OBJ_TAG:
+ handle_tag(name, (struct tag *)object);
+ break;
+ case OBJ_COMMIT:
+ /* create refs pointing to already seen commits */
+ commit = (struct commit *)object;
+ printf("reset %s\nfrom :%d\n\n", name,
+ get_object_mark(&commit->object));
+ show_progress();
+ break;
+ }
+ }
+}
+
+int cmd_fast_export(int argc, const char **argv, const char *prefix)
+{
+ struct rev_info revs;
+ struct object_array commits = { 0, 0, NULL };
+ struct path_list extra_refs = { NULL, 0, 0, 0 };
+ struct commit *commit;
+ struct option options[] = {
+ OPT_INTEGER(0, "progress", &progress,
+ "show progress after <n> objects"),
+ OPT_CALLBACK(0, "signed-tags", &signed_tag_mode, "mode",
+ "select handling of signed tags",
+ parse_opt_signed_tag_mode),
+ OPT_END()
+ };
+
+ /* we handle encodings */
+ git_config(git_default_config);
+
+ init_revisions(&revs, prefix);
+ argc = setup_revisions(argc, argv, &revs, NULL);
+ argc = parse_options(argc, argv, options, fast_export_usage, 0);
+ if (argc > 1)
+ usage_with_options (fast_export_usage, options);
+
+ get_tags_and_duplicates(&revs.pending, &extra_refs);
+
+ prepare_revision_walk(&revs);
+ revs.diffopt.format_callback = show_filemodify;
+ DIFF_OPT_SET(&revs.diffopt, RECURSIVE);
+ while ((commit = get_revision(&revs))) {
+ if (has_unshown_parent(commit)) {
+ struct commit_list *parent = commit->parents;
+ add_object_array(&commit->object, NULL, &commits);
+ for (; parent; parent = parent->next)
+ if (!parent->item->util)
+ parent->item->util = commit->util;
+ }
+ else {
+ handle_commit(commit, &revs);
+ handle_tail(&commits, &revs);
+ }
+ }
+
+ handle_tags_and_duplicates(&extra_refs);
+
+ return 0;
+}
diff --git a/builtin.h b/builtin.h
index 3055bcc..142ab63 100644
--- a/builtin.h
+++ b/builtin.h
@@ -33,6 +33,7 @@ extern int cmd_diff_files(int argc, const char **argv, const char *prefix);
extern int cmd_diff_index(int argc, const char **argv, const char *prefix);
extern int cmd_diff(int argc, const char **argv, const char *prefix);
extern int cmd_diff_tree(int argc, const char **argv, const char *prefix);
+extern int cmd_fast_export(int argc, const char **argv, const char *prefix);
extern int cmd_fetch(int argc, const char **argv, const char *prefix);
extern int cmd_fetch_pack(int argc, const char **argv, const char *prefix);
extern int cmd_fetch__tool(int argc, const char **argv, const char *prefix);
diff --git a/git.c b/git.c
index e48c2c9..db0e7c3 100644
--- a/git.c
+++ b/git.c
@@ -303,6 +303,7 @@ static void handle_internal_command(int argc, const char **argv)
{ "diff-files", cmd_diff_files },
{ "diff-index", cmd_diff_index, RUN_SETUP },
{ "diff-tree", cmd_diff_tree, RUN_SETUP },
+ { "fast-export", cmd_fast_export, RUN_SETUP },
{ "fetch", cmd_fetch, RUN_SETUP },
{ "fetch-pack", cmd_fetch_pack, RUN_SETUP },
{ "fetch--tool", cmd_fetch__tool, RUN_SETUP },
diff --git a/t/t9301-fast-export.sh b/t/t9301-fast-export.sh
new file mode 100755
index 0000000..59f6996
--- /dev/null
+++ b/t/t9301-fast-export.sh
@@ -0,0 +1,124 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 Johannes E. Schindelin
+#
+
+test_description='git-fast-export'
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+
+ echo Wohlauf > file &&
+ git add file &&
+ test_tick &&
+ git commit -m initial &&
+ echo die Luft > file &&
+ echo geht frisch > file2 &&
+ git add file file2 &&
+ test_tick &&
+ git commit -m second &&
+ echo und > file2 &&
+ test_tick &&
+ git commit -m third file2 &&
+ test_tick &&
+ git tag rein &&
+ git checkout -b wer HEAD^ &&
+ echo lange > file2
+ test_tick &&
+ git commit -m sitzt file2 &&
+ test_tick &&
+ git tag -a -m valentin muss &&
+ git merge -s ours master
+
+'
+
+test_expect_success 'fast-export | fast-import' '
+
+ MASTER=$(git rev-parse --verify master) &&
+ REIN=$(git rev-parse --verify rein) &&
+ WER=$(git rev-parse --verify wer) &&
+ MUSS=$(git rev-parse --verify muss) &&
+ mkdir new &&
+ git --git-dir=new/.git init &&
+ git fast-export --all |
+ (cd new &&
+ git fast-import &&
+ test $MASTER = $(git rev-parse --verify refs/heads/master) &&
+ test $REIN = $(git rev-parse --verify refs/tags/rein) &&
+ test $WER = $(git rev-parse --verify refs/heads/wer) &&
+ test $MUSS = $(git rev-parse --verify refs/tags/muss))
+
+'
+
+test_expect_success 'fast-export master~2..master' '
+
+ git fast-export master~2..master |
+ sed "s/master/partial/" |
+ (cd new &&
+ git fast-import &&
+ test $MASTER != $(git rev-parse --verify refs/heads/partial) &&
+ git diff master..partial &&
+ git diff master^..partial^ &&
+ ! git rev-parse partial~2)
+
+'
+
+test_expect_success 'iso-8859-1' '
+
+ git config i18n.commitencoding ISO-8859-1 &&
+ # use author and committer name in ISO-8859-1 to match it.
+ . ../t3901-8859-1.txt &&
+ test_tick &&
+ echo rosten >file &&
+ git commit -s -m den file &&
+ git fast-export wer^..wer |
+ sed "s/wer/i18n/" |
+ (cd new &&
+ git fast-import &&
+ git cat-file commit i18n | grep "Áéí óú")
+
+'
+
+cat > signed-tag-import << EOF
+tag sign-your-name
+from $(git rev-parse HEAD)
+tagger C O Mitter <committer@example.com> 1112911993 -0700
+data 210
+A message for a sign
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.5 (GNU/Linux)
+
+fakedsignaturefakedsignaturefakedsignaturefakedsignaturfakedsign
+aturefakedsignaturefake=
+=/59v
+-----END PGP SIGNATURE-----
+EOF
+
+test_expect_success 'set up faked signed tag' '
+
+ cat signed-tag-import | git fast-import
+
+'
+
+test_expect_success 'signed-tags=abort' '
+
+ ! git fast-export --signed-tags=abort sign-your-name
+
+'
+
+test_expect_success 'signed-tags=ignore' '
+
+ git fast-export --signed-tags=ignore sign-your-name > output &&
+ grep PGP output
+
+'
+
+test_expect_success 'signed-tags=strip' '
+
+ git fast-export --signed-tags=strip sign-your-name > output &&
+ ! grep PGP output
+
+'
+
+test_done
+
--
1.5.3.6.1828.gd496
^ permalink raw reply related
* [Resend Trivial PATCH] Print the real filename whose opening failed.
From: André Goddard Rosa @ 2007-11-25 21:38 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git Mailing List
In-Reply-To: <b8bf37780711211700g48a738b1xa147d1e7000ee76@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2905 bytes --]
Hi, all!
Print the filename whose opening failed.
From 88b7bd873b97bd81e854827c9cd8f3c306d3c3af Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Andr=C3=A9=20Goddard=20Rosa?= <andre.goddard@gmail.com>
Date: Wed, 21 Nov 2007 18:59:14 -0200
Subject: [PATCH] Print the real filename whose opening failed.
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
Signed-off-by: André Goddard Rosa <andre.goddard@gmail.com>
---
http-push.c | 4 ++--
http-walker.c | 4 ++--
server-info.c | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/http-push.c b/http-push.c
index 9314621..e675ca6 100644
--- a/http-push.c
+++ b/http-push.c
@@ -433,7 +433,7 @@ static void start_fetch_packed(struct
transfer_request *request)
packfile = fopen(request->tmpfile, "a");
if (!packfile) {
fprintf(stderr, "Unable to open local file %s for pack",
- filename);
+ request->tmpfile);
remote->can_update_info_refs = 0;
free(url);
return;
@@ -941,7 +941,7 @@ static int fetch_index(unsigned char *sha1)
indexfile = fopen(tmpfile, "a");
if (!indexfile)
return error("Unable to open local file %s for pack index",
- filename);
+ tmpfile);
slot = get_active_slot();
slot->results = &results;
diff --git a/http-walker.c b/http-walker.c
index 444aebf..a3fb596 100644
--- a/http-walker.c
+++ b/http-walker.c
@@ -405,7 +405,7 @@ static int fetch_index(struct walker *walker,
struct alt_base *repo, unsigned ch
indexfile = fopen(tmpfile, "a");
if (!indexfile)
return error("Unable to open local file %s for pack index",
- filename);
+ tmpfile);
slot = get_active_slot();
slot->results = &results;
@@ -770,7 +770,7 @@ static int fetch_pack(struct walker *walker,
struct alt_base *repo, unsigned cha
packfile = fopen(tmpfile, "a");
if (!packfile)
return error("Unable to open local file %s for pack",
- filename);
+ tmpfile);
slot = get_active_slot();
slot->results = &results;
diff --git a/server-info.c b/server-info.c
index 0d1312c..a051e49 100644
--- a/server-info.c
+++ b/server-info.c
@@ -35,7 +35,7 @@ static int update_info_refs(int force)
safe_create_leading_directories(path0);
info_ref_fp = fopen(path1, "w");
if (!info_ref_fp)
- return error("unable to update %s", path0);
+ return error("unable to update %s", path1);
for_each_ref(add_info_ref, NULL);
fclose(info_ref_fp);
adjust_shared_perm(path1);
--
1.5.3.6.861.gd794-dirty
--
[]s,
André Goddard
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0005-Print-the-real-filename-whose-opening-failed.patch --]
[-- Type: text/x-patch; name=0005-Print-the-real-filename-whose-opening-failed.patch, Size: 2430 bytes --]
From 88b7bd873b97bd81e854827c9cd8f3c306d3c3af Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Andr=C3=A9=20Goddard=20Rosa?= <andre.goddard@gmail.com>
Date: Wed, 21 Nov 2007 18:59:14 -0200
Subject: [PATCH] Print the real filename whose opening failed.
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
Signed-off-by: André Goddard Rosa <andre.goddard@gmail.com>
---
http-push.c | 4 ++--
http-walker.c | 4 ++--
server-info.c | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/http-push.c b/http-push.c
index 9314621..e675ca6 100644
--- a/http-push.c
+++ b/http-push.c
@@ -433,7 +433,7 @@ static void start_fetch_packed(struct transfer_request *request)
packfile = fopen(request->tmpfile, "a");
if (!packfile) {
fprintf(stderr, "Unable to open local file %s for pack",
- filename);
+ request->tmpfile);
remote->can_update_info_refs = 0;
free(url);
return;
@@ -941,7 +941,7 @@ static int fetch_index(unsigned char *sha1)
indexfile = fopen(tmpfile, "a");
if (!indexfile)
return error("Unable to open local file %s for pack index",
- filename);
+ tmpfile);
slot = get_active_slot();
slot->results = &results;
diff --git a/http-walker.c b/http-walker.c
index 444aebf..a3fb596 100644
--- a/http-walker.c
+++ b/http-walker.c
@@ -405,7 +405,7 @@ static int fetch_index(struct walker *walker, struct alt_base *repo, unsigned ch
indexfile = fopen(tmpfile, "a");
if (!indexfile)
return error("Unable to open local file %s for pack index",
- filename);
+ tmpfile);
slot = get_active_slot();
slot->results = &results;
@@ -770,7 +770,7 @@ static int fetch_pack(struct walker *walker, struct alt_base *repo, unsigned cha
packfile = fopen(tmpfile, "a");
if (!packfile)
return error("Unable to open local file %s for pack",
- filename);
+ tmpfile);
slot = get_active_slot();
slot->results = &results;
diff --git a/server-info.c b/server-info.c
index 0d1312c..a051e49 100644
--- a/server-info.c
+++ b/server-info.c
@@ -35,7 +35,7 @@ static int update_info_refs(int force)
safe_create_leading_directories(path0);
info_ref_fp = fopen(path1, "w");
if (!info_ref_fp)
- return error("unable to update %s", path0);
+ return error("unable to update %s", path1);
for_each_ref(add_info_ref, NULL);
fclose(info_ref_fp);
adjust_shared_perm(path1);
--
1.5.3.6.861.gd794-dirty
^ permalink raw reply related
* [Resend PATCH] Fix segmentation fault when user doesn't have access permission to the repository.
From: André Goddard Rosa @ 2007-11-25 21:39 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git Mailing List
In-Reply-To: <b8bf37780711221427q5dda709dt38ce1837c0e56c1f@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 5302 bytes --]
On Nov 22, 2007 2:09 PM, Alex Riesen <raa.lkml@gmail.com> wrote:
> André Goddard Rosa, Thu, Nov 22, 2007 01:59:00 +0100:
> > @@ -487,8 +490,13 @@ static int do_fetch(struct transport *transport,
> > die("Don't know how to fetch from %s", transport->url);
> >
> > /* if not appending, truncate FETCH_HEAD */
> > - if (!append)
> > - fclose(fopen(git_path("FETCH_HEAD"), "w"));
> > + if (!append) {
> > + char *filename = git_path("FETCH_HEAD");
> > + int fd = fopen(filename, "w");
>
> This should have been "FILE *fp", not "int fd".
>
Hi, Alex!
Many thanks, you're right.
I tested it here before posting but luckly (or not, as I didn't catch
this when compiling) it worked,
as a pointer have the sizeof(int) in my x86 platform. >:|
Would you please comment on the attached patch and see if it's ok?
From dbadc5213b9957fb575c6da8528e5dd7a3f1f43e Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Andr=C3=A9=20Goddard=20Rosa?= <andre.goddard@gmail.com>
Date: Thu, 22 Nov 2007 20:22:23 -0200
Subject: [PATCH] Fix segmentation fault when user doesn't have access
permission to the repository.
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
Signed-off-by: André Goddard Rosa <andre.goddard@gmail.com>
---
builtin-fetch--tool.c | 12 ++++++++++--
builtin-fetch.c | 21 ++++++++++++++++-----
2 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c
index ed60847..7460ab7 100644
--- a/builtin-fetch--tool.c
+++ b/builtin-fetch--tool.c
@@ -511,10 +511,14 @@ int cmd_fetch__tool(int argc, const char **argv,
const char *prefix)
if (!strcmp("append-fetch-head", argv[1])) {
int result;
FILE *fp;
+ char *filename;
if (argc != 8)
return error("append-fetch-head takes 6 args");
- fp = fopen(git_path("FETCH_HEAD"), "a");
+ filename = git_path("FETCH_HEAD");
+ fp = fopen(filename, "a");
+ if (!fp)
+ return error("cannot open %s: %s\n", filename,
strerror(errno));
result = append_fetch_head(fp, argv[2], argv[3],
argv[4], argv[5],
argv[6], !!argv[7][0],
@@ -525,10 +529,14 @@ int cmd_fetch__tool(int argc, const char **argv,
const char *prefix)
if (!strcmp("native-store", argv[1])) {
int result;
FILE *fp;
+ char *filename;
if (argc != 5)
return error("fetch-native-store takes 3 args");
- fp = fopen(git_path("FETCH_HEAD"), "a");
+ filename = git_path("FETCH_HEAD");
+ fp = fopen(filename, "a");
+ if (!fp)
+ return error("cannot open %s: %s\n", filename,
strerror(errno));
result = fetch_native_store(fp, argv[2], argv[3], argv[4],
verbose, force);
fclose(fp);
diff --git a/builtin-fetch.c b/builtin-fetch.c
index be9e3ea..84c8ed4 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -255,7 +255,7 @@ static int update_local_ref(struct ref *ref,
}
}
-static void store_updated_refs(const char *url, struct ref *ref_map)
+static int store_updated_refs(const char *url, struct ref *ref_map)
{
FILE *fp;
struct commit *commit;
@@ -263,8 +263,13 @@ static void store_updated_refs(const char *url,
struct ref *ref_map)
char note[1024];
const char *what, *kind;
struct ref *rm;
+ char *filename = git_path("FETCH_HEAD");
- fp = fopen(git_path("FETCH_HEAD"), "a");
+ fp = fopen(filename, "a");
+ if (!fp) {
+ error("cannot open %s: %s\n", filename, strerror(errno));
+ return 1;
+ }
for (rm = ref_map; rm; rm = rm->next) {
struct ref *ref = NULL;
@@ -335,6 +340,7 @@ static void store_updated_refs(const char *url,
struct ref *ref_map)
}
}
fclose(fp);
+ return 0;
}
/*
@@ -404,7 +410,7 @@ static int fetch_refs(struct transport *transport,
struct ref *ref_map)
if (ret)
ret = transport_fetch_refs(transport, ref_map);
if (!ret)
- store_updated_refs(transport->url, ref_map);
+ ret |= store_updated_refs(transport->url, ref_map);
transport_unlock_pack(transport);
return ret;
}
@@ -487,8 +493,13 @@ static int do_fetch(struct transport *transport,
die("Don't know how to fetch from %s", transport->url);
/* if not appending, truncate FETCH_HEAD */
- if (!append)
- fclose(fopen(git_path("FETCH_HEAD"), "w"));
+ if (!append) {
+ char *filename = git_path("FETCH_HEAD");
+ FILE *fp = fopen(filename, "w");
+ if (!fp)
+ return error("cannot open %s: %s\n", filename,
strerror(errno));
+ fclose(fp);
+ }
ref_map = get_ref_map(transport, refs, ref_count, tags, &autotags);
--
1.5.3.6.861.gd794-dirty
--
[]s,
André Goddard
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Fix-segmentation-fault-when-user-doesn-t-have-access.patch --]
[-- Type: text/x-patch; name=0001-Fix-segmentation-fault-when-user-doesn-t-have-access.patch, Size: 3642 bytes --]
From dbadc5213b9957fb575c6da8528e5dd7a3f1f43e Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Andr=C3=A9=20Goddard=20Rosa?= <andre.goddard@gmail.com>
Date: Thu, 22 Nov 2007 20:22:23 -0200
Subject: [PATCH] Fix segmentation fault when user doesn't have access
permission to the repository.
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
Signed-off-by: André Goddard Rosa <andre.goddard@gmail.com>
---
builtin-fetch--tool.c | 12 ++++++++++--
builtin-fetch.c | 21 ++++++++++++++++-----
2 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c
index ed60847..7460ab7 100644
--- a/builtin-fetch--tool.c
+++ b/builtin-fetch--tool.c
@@ -511,10 +511,14 @@ int cmd_fetch__tool(int argc, const char **argv, const char *prefix)
if (!strcmp("append-fetch-head", argv[1])) {
int result;
FILE *fp;
+ char *filename;
if (argc != 8)
return error("append-fetch-head takes 6 args");
- fp = fopen(git_path("FETCH_HEAD"), "a");
+ filename = git_path("FETCH_HEAD");
+ fp = fopen(filename, "a");
+ if (!fp)
+ return error("cannot open %s: %s\n", filename, strerror(errno));
result = append_fetch_head(fp, argv[2], argv[3],
argv[4], argv[5],
argv[6], !!argv[7][0],
@@ -525,10 +529,14 @@ int cmd_fetch__tool(int argc, const char **argv, const char *prefix)
if (!strcmp("native-store", argv[1])) {
int result;
FILE *fp;
+ char *filename;
if (argc != 5)
return error("fetch-native-store takes 3 args");
- fp = fopen(git_path("FETCH_HEAD"), "a");
+ filename = git_path("FETCH_HEAD");
+ fp = fopen(filename, "a");
+ if (!fp)
+ return error("cannot open %s: %s\n", filename, strerror(errno));
result = fetch_native_store(fp, argv[2], argv[3], argv[4],
verbose, force);
fclose(fp);
diff --git a/builtin-fetch.c b/builtin-fetch.c
index be9e3ea..84c8ed4 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -255,7 +255,7 @@ static int update_local_ref(struct ref *ref,
}
}
-static void store_updated_refs(const char *url, struct ref *ref_map)
+static int store_updated_refs(const char *url, struct ref *ref_map)
{
FILE *fp;
struct commit *commit;
@@ -263,8 +263,13 @@ static void store_updated_refs(const char *url, struct ref *ref_map)
char note[1024];
const char *what, *kind;
struct ref *rm;
+ char *filename = git_path("FETCH_HEAD");
- fp = fopen(git_path("FETCH_HEAD"), "a");
+ fp = fopen(filename, "a");
+ if (!fp) {
+ error("cannot open %s: %s\n", filename, strerror(errno));
+ return 1;
+ }
for (rm = ref_map; rm; rm = rm->next) {
struct ref *ref = NULL;
@@ -335,6 +340,7 @@ static void store_updated_refs(const char *url, struct ref *ref_map)
}
}
fclose(fp);
+ return 0;
}
/*
@@ -404,7 +410,7 @@ static int fetch_refs(struct transport *transport, struct ref *ref_map)
if (ret)
ret = transport_fetch_refs(transport, ref_map);
if (!ret)
- store_updated_refs(transport->url, ref_map);
+ ret |= store_updated_refs(transport->url, ref_map);
transport_unlock_pack(transport);
return ret;
}
@@ -487,8 +493,13 @@ static int do_fetch(struct transport *transport,
die("Don't know how to fetch from %s", transport->url);
/* if not appending, truncate FETCH_HEAD */
- if (!append)
- fclose(fopen(git_path("FETCH_HEAD"), "w"));
+ if (!append) {
+ char *filename = git_path("FETCH_HEAD");
+ FILE *fp = fopen(filename, "w");
+ if (!fp)
+ return error("cannot open %s: %s\n", filename, strerror(errno));
+ fclose(fp);
+ }
ref_map = get_ref_map(transport, refs, ref_count, tags, &autotags);
--
1.5.3.6.861.gd794-dirty
^ permalink raw reply related
* [Resend PATCH] Simplify the code and avoid an assignment
From: André Goddard Rosa @ 2007-11-25 21:42 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git Mailing List
[-- Attachment #1: Type: text/plain, Size: 2247 bytes --]
Hi, all!
Simplify the code for easier understanding.
>From cd0cc6995684e2801011910735146052e5b59ccc Mon Sep 17 00:00:00 2001
From: Andre Goddard Rosa <andre.goddard@gmail.com>
Date: Tue, 27 Nov 2007 10:22:46 -0200
Subject: [PATCH] Simplify the code and avoid an assignment.
Signed-off-by: Andre Goddard Rosa <andre.goddard@gmail.com>
---
config.c | 19 ++++++++++---------
mailmap.c | 2 +-
xdiff-interface.c | 2 +-
3 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/config.c b/config.c
index 56e99fc..7c9fcdd 100644
--- a/config.c
+++ b/config.c
@@ -447,15 +447,16 @@ int git_config_from_file(config_fn_t fn, const
char *filename)
int ret;
FILE *f = fopen(filename, "r");
- ret = -1;
- if (f) {
- config_file = f;
- config_file_name = filename;
- config_linenr = 1;
- ret = git_parse_file(fn);
- fclose(f);
- config_file_name = NULL;
- }
+ if (!f)
+ return -1;
+
+ config_file = f;
+ config_file_name = filename;
+ config_linenr = 1;
+ ret = git_parse_file(fn);
+ fclose(f);
+ config_file_name = NULL;
+
return ret;
}
diff --git a/mailmap.c b/mailmap.c
index 8714167..0c13ecd 100644
--- a/mailmap.c
+++ b/mailmap.c
@@ -7,7 +7,7 @@ int read_mailmap(struct path_list *map, const char
*filename, char **repo_abbrev
char buffer[1024];
FILE *f = fopen(filename, "r");
- if (f == NULL)
+ if (!f)
return 1;
while (fgets(buffer, sizeof(buffer), f) != NULL) {
char *end_of_name, *left_bracket, *right_bracket;
diff --git a/xdiff-interface.c b/xdiff-interface.c
index be866d1..9dd1f3b 100644
--- a/xdiff-interface.c
+++ b/xdiff-interface.c
@@ -111,7 +111,7 @@ int read_mmfile(mmfile_t *ptr, const char *filename)
if (stat(filename, &st))
return error("Could not stat %s", filename);
- if ((f = fopen(filename, "rb")) == NULL)
+ if (!(f = fopen(filename, "rb")))
return error("Could not open %s", filename);
sz = xsize_t(st.st_size);
ptr->ptr = xmalloc(sz);
--
1.5.3.6.861.gd794-dirty
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0004-Simplify-the-code-and-avoid-an-assignment.patch --]
[-- Type: text/x-patch; name=0004-Simplify-the-code-and-avoid-an-assignment.patch, Size: 1911 bytes --]
From cd0cc6995684e2801011910735146052e5b59ccc Mon Sep 17 00:00:00 2001
From: Andre Goddard Rosa <andre.goddard@gmail.com>
Date: Tue, 27 Nov 2007 10:22:46 -0200
Subject: [PATCH] Simplify the code and avoid an assignment.
Signed-off-by: Andre Goddard Rosa <andre.goddard@gmail.com>
---
config.c | 19 ++++++++++---------
mailmap.c | 2 +-
xdiff-interface.c | 2 +-
3 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/config.c b/config.c
index 56e99fc..7c9fcdd 100644
--- a/config.c
+++ b/config.c
@@ -447,15 +447,16 @@ int git_config_from_file(config_fn_t fn, const char *filename)
int ret;
FILE *f = fopen(filename, "r");
- ret = -1;
- if (f) {
- config_file = f;
- config_file_name = filename;
- config_linenr = 1;
- ret = git_parse_file(fn);
- fclose(f);
- config_file_name = NULL;
- }
+ if (!f)
+ return -1;
+
+ config_file = f;
+ config_file_name = filename;
+ config_linenr = 1;
+ ret = git_parse_file(fn);
+ fclose(f);
+ config_file_name = NULL;
+
return ret;
}
diff --git a/mailmap.c b/mailmap.c
index 8714167..0c13ecd 100644
--- a/mailmap.c
+++ b/mailmap.c
@@ -7,7 +7,7 @@ int read_mailmap(struct path_list *map, const char *filename, char **repo_abbrev
char buffer[1024];
FILE *f = fopen(filename, "r");
- if (f == NULL)
+ if (!f)
return 1;
while (fgets(buffer, sizeof(buffer), f) != NULL) {
char *end_of_name, *left_bracket, *right_bracket;
diff --git a/xdiff-interface.c b/xdiff-interface.c
index be866d1..9dd1f3b 100644
--- a/xdiff-interface.c
+++ b/xdiff-interface.c
@@ -111,7 +111,7 @@ int read_mmfile(mmfile_t *ptr, const char *filename)
if (stat(filename, &st))
return error("Could not stat %s", filename);
- if ((f = fopen(filename, "rb")) == NULL)
+ if (!(f = fopen(filename, "rb")))
return error("Could not open %s", filename);
sz = xsize_t(st.st_size);
ptr->ptr = xmalloc(sz);
--
1.5.3.6.861.gd794-dirty
^ permalink raw reply related
* [Resend PATCH] Avoid recalculating filename string pointer.
From: André Goddard Rosa @ 2007-11-25 21:43 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git Mailing List
In-Reply-To: <b8bf37780711211659i65a99493te3e3d5cee008ae7d@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1446 bytes --]
Hi, all!
Avoid calculating string position in 2 different places.
From b6b05d9f8d8e053df4e971cd229e03b778c4d163 Mon Sep 17 00:00:00 2001
From: Andre Goddard Rosa <andre.goddard@gmail.com>
Date: Tue, 27 Nov 2007 10:17:54 -0200
Subject: [PATCH] Avoid recalculating filename string pointer.
Signed-off-by: Andre Goddard Rosa <andre.goddard@gmail.com>
---
fast-import.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/fast-import.c b/fast-import.c
index 98c2bd5..2d262eb 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -2304,11 +2304,13 @@ int main(int argc, const char **argv)
else if (!prefixcmp(a, "--export-marks="))
mark_file = a + 15;
else if (!prefixcmp(a, "--export-pack-edges=")) {
+ char *filename = a + 20;
+
if (pack_edges)
fclose(pack_edges);
- pack_edges = fopen(a + 20, "a");
+ pack_edges = fopen(filename, "a");
if (!pack_edges)
- die("Cannot open %s: %s", a + 20,
strerror(errno));
+ die("Cannot open %s: %s", filename,
strerror(errno));
} else if (!strcmp(a, "--force"))
force_update = 1;
else if (!strcmp(a, "--quiet"))
--
1.5.3.6.861.gd794-dirty
--
[]s,
André Goddard
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0003-Avoid-recalculating-filename-string-pointer.patch --]
[-- Type: text/x-patch; name=0003-Avoid-recalculating-filename-string-pointer.patch, Size: 1077 bytes --]
From b6b05d9f8d8e053df4e971cd229e03b778c4d163 Mon Sep 17 00:00:00 2001
From: Andre Goddard Rosa <andre.goddard@gmail.com>
Date: Tue, 27 Nov 2007 10:17:54 -0200
Subject: [PATCH] Avoid recalculating filename string pointer.
Signed-off-by: Andre Goddard Rosa <andre.goddard@gmail.com>
---
fast-import.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/fast-import.c b/fast-import.c
index 98c2bd5..2d262eb 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -2304,11 +2304,13 @@ int main(int argc, const char **argv)
else if (!prefixcmp(a, "--export-marks="))
mark_file = a + 15;
else if (!prefixcmp(a, "--export-pack-edges=")) {
+ char *filename = a + 20;
+
if (pack_edges)
fclose(pack_edges);
- pack_edges = fopen(a + 20, "a");
+ pack_edges = fopen(filename, "a");
if (!pack_edges)
- die("Cannot open %s: %s", a + 20, strerror(errno));
+ die("Cannot open %s: %s", filename, strerror(errno));
} else if (!strcmp(a, "--force"))
force_update = 1;
else if (!strcmp(a, "--quiet"))
--
1.5.3.6.861.gd794-dirty
^ permalink raw reply related
* If you would write git from scratch now, what would you change?
From: Jakub Narebski @ 2007-11-25 21:48 UTC (permalink / raw)
To: git
If you would write git from scratch now, from the beginning, without
concerns for backwards compatibility, what would you change, or what
would you want to have changed?
Yes, I know, I know. "Worse is better". It is better to release early
and get feedback what is really needed, as opposed to what do you think
is needed.
I think git is a wonderful example of "evolved" software, evolving
practically from the very beginnings.
--
Jakub Narebski
Poland
^ permalink raw reply
* Re: What's cooking in git.git (topics)
From: J. Bruce Fields @ 2007-11-25 21:51 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Nicolas Pitre, Jeff King, Johannes Schindelin, git
In-Reply-To: <7vtznbqx2w.fsf@gitster.siamese.dyndns.org>
On Sat, Nov 24, 2007 at 11:09:59AM -0800, Junio C Hamano wrote:
> Nicolas Pitre <nico@cam.org> writes:
> > I think that would be better to append a single line at the end of the
> > display with a clue about what "non fast forward" means.
>
> I'd agree, but having said all the above, I am not entirely
> happy not mentioning "what next" at all.
>
> There are two equally valid "what next" after your push is
> rejected due to non-fast-forwardness.
>
> (1) You know what you are doing.
>
> - You are pushing into a "back-up" repository, not for a
> public consumption.
>
> - You are pushing a branch that are advertised to rebase and
> rewind into your own publishing repository, and other
> people interacting with the branch know about this.
>
> - You pushed a wrong head there very recently and are fairly
> confident that nobody has seen that mistake, and pushing
> the correct one to fix the mistake.
>
> In these cases, forcing the push is the right solution
> (except that the third one is dubious, because it depends
> heavily on the "fairly confident" part).
>
> (2) You were building on a stale head, and were indeed about to
> lose others' changes with a non-fast-forward push.
>
> The right solution is to rebuild what you push so that you
> will not lose others' changes. Rebuilding can take two
> different forms:
>
> - You may want to git-fetch and rebase your work on top of
> others'.
>
> - You may want to git-pull, which will merge your work with
> what others did.
>
> But of couse the above is way too long as the help text.
>
> Does the user-manual talk about this? It has a really good
> description of how to notice when a merge is not resolved
> automatically and what to do next ("Resolving a merge" section).
> Perhaps we can enhance "Pushing changes to a public repository"
> section to include "what if the push is refused" information.
There's a very brief mention of this:
"As with git-fetch, git-push will complain if this does not
result in a <<fast-forwards,fast forward>>. Normally this is a
sign of something wrong. However, if you are sure you know what
you're doing, you may force git-push to perform the update
anyway by preceding the branch name by a plus sign:
But it'd probably be better to have a separate section. That makes it
possible to say a little more, and also gets a section called "what to
do when a push fails" into the table of contents.
(Though that's a little vague--push can also fail just because you
mispell the url or something. A more precise reference to the
particular error might be better, but we'll have to agree on the error
message first....)
Anyway, here's a first draft.
--b.
diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt
index 8355cce..7544715 100644
--- a/Documentation/user-manual.txt
+++ b/Documentation/user-manual.txt
@@ -1929,15 +1929,9 @@ or just
$ git push ssh://yourserver.com/~you/proj.git master
-------------------------------------------------
-As with git-fetch, git-push will complain if this does not result in
-a <<fast-forwards,fast forward>>. Normally this is a sign of
-something wrong. However, if you are sure you know what you're
-doing, you may force git-push to perform the update anyway by
-proceeding the branch name by a plus sign:
-
--------------------------------------------------
-$ git push ssh://yourserver.com/~you/proj.git +master
--------------------------------------------------
+As with git-fetch, git-push will complain if this does not result in a
+<<fast-forwards,fast forward>>; see the following section for details on
+handling this case.
Note that the target of a "push" is normally a
<<def_bare_repository,bare>> repository. You can also push to a
@@ -1965,6 +1959,55 @@ See the explanations of the remote.<name>.url, branch.<name>.remote,
and remote.<name>.push options in gitlink:git-config[1] for
details.
+[[forcing-push]]
+What to do when a push fails
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If the push does not result in a <<fast-forwards,fast forward>> of the
+remote branch, then it will fail with an error like:
+
+-------------------------------------------------
+error: remote 'refs/heads/master' is not an ancestor of
+ local 'refs/heads/master'.
+ Maybe you are not up-to-date and need to pull first?
+error: failed to push to 'ssh://yourserver.com/~you/proj.git'
+-------------------------------------------------
+
+The most likely reason for this is that you have replaced some of the
+history that you already pushed, so that your "master" is no longer a
+descendant of upstream's "master", This could happen, for example, if
+you:
+
+ - use `git reset --hard` to remove already-published commits, or
+ - use `git commit --amend` to replace already-published commits
+ (as in <<fixing-a-mistake-by-editing-history>>), or
+ - use `git rebase` to rebase any already-published commits (as
+ in <<using-git-rebase>>).
+
+If you are sure you want to replace the branch in the public repository
+by your branch, you may force git-push to perform the update anyway by
+preceding the branch name with a plus sign:
+
+-------------------------------------------------
+$ git push ssh://yourserver.com/~you/proj.git +master
+-------------------------------------------------
+
+Normally whenever a branch head in a public repository is modified, it
+is modified to point to a descendent of the commit that it pointed to
+before. By forcing a push in this situation, you break that convention.
+(See <<problems-with-rewriting-history>>).
+
+Nevertheless, this is a common practice for people that need a simple
+way to publish a work-in-progress patch series, and it is an acceptable
+compromise as long as you warn other developers that this is how you
+intend to manage the branch.
+
+It's also possible for a push to fail in this way when other people have
+the right to push to the same repository. In that case, the correct
+solution is to update your work by either a pull or a fetch followed by
+a rebase; see the <<setting-up-a-shared-repository,next section>> for
+more.
+
[[setting-up-a-shared-repository]]
Setting up a shared repository
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
^ permalink raw reply related
* Re: [PATCH 3/2] core.whitespace: documentation updates.
From: J. Bruce Fields @ 2007-11-25 21:58 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7v3auvqq09.fsf@gitster.siamese.dyndns.org>
On Sat, Nov 24, 2007 at 01:42:46PM -0800, Junio C Hamano wrote:
> "J. Bruce Fields" <bfields@fieldses.org> writes:
>
> > I'd still prefer this to be a gitattributes thing rather than a config
> > variable[1]. Last time I raised this you said something to the effect
> > of "I think you're right, let's fix that before it's merged." Would you
> > like me to work on that?
>
> Ah, I forgot about that, and you are right. Go wild.
OK, I will go wild, but... very slowly.
--b.
^ permalink raw reply
* Re: [RFC] best way to show diff of commit
From: Pierre Habouzit @ 2007-11-25 22:09 UTC (permalink / raw)
To: J. Bruce Fields; +Cc: Git ML
In-Reply-To: <20071125212748.GB23820@fieldses.org>
[-- Attachment #1: Type: text/plain, Size: 1735 bytes --]
On Sun, Nov 25, 2007 at 09:27:48PM +0000, J. Bruce Fields wrote:
> On Sun, Nov 25, 2007 at 10:18:31PM +0100, Pierre Habouzit wrote:
> > There is specific script I run in my vim with git, that tries to show
> > from the 'status' git commit shows in the buffer which list of files has
> > changed, and builds a diff from it quite clumsily[0].
> >
> > I wonder how hard it would be for git commit to "stash" the current
> > commit being sent somewhere editors would be able to have a look at (an
> > alternate index is probably fine). Note that maybe I'm stupid and
> > overlooked that such a thing already exists. I'd like to have it in two
> > flavors: normal and amend mode. normal mode would show what the
> > resulting commit diff looks like, and the amend mode only shows the
> > incrementall diff the amend adds to the previous commit.
> >
> > My question is: what do you think is the best way to do that, and
> > where ?
>
> Have you checked whether "git-commit -v" already does what you want?
Hmm it doesn't because I would have to call git commit -v each time I
commit and well I _like_ having the status better. And moreover I want
the diff to go in a separated buffer too.
I'd rather have some kind of way to have git-commit let a trail of
what he's doing if the user validate the commit, and use that from the
editor. I'm sure it would be useful to simple GUIs as well (most
advanced GUIs would like to have fine control to what gets commited and
are likely to have the command like used quite right).
--
·O· Pierre Habouzit
··O madcoder@debian.org
OOO http://www.madism.org
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: If you would write git from scratch now, what would you change?
From: Pierre Habouzit @ 2007-11-25 22:23 UTC (permalink / raw)
To: Jakub Narebski; +Cc: git
In-Reply-To: <200711252248.27904.jnareb@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1893 bytes --]
On Sun, Nov 25, 2007 at 09:48:27PM +0000, Jakub Narebski wrote:
> If you would write git from scratch now, from the beginning, without
> concerns for backwards compatibility, what would you change, or what
> would you want to have changed?
* reset/checkout/revert. The commands to wonderful things, but this UI
is a mess for the newcomer.
* pull/fetch/push: I would have had pull being what fetch is, and
added some --merge option to actually "do the obvious merge". But
pull encourage "bad" behavior from the user, and confuses newcomers
a lot.
* I would have hidden plumbing more, using a really distinguished
namespace (stupid example, there are probably better ways, but we
could have git-_rev-parse or git-plumbing-rev-parse instead of
git-rev-parse) so that it's clear to the user that those are really
internal commands, and that he doesn't need to understand them.
This is a big issue with git: the list of commands of git is the top
of the iceberg from the UI point of view. People _feel_ they are
comfortable with a tool if they get say 75% of the UI. I don't say
it's true that understanding 75% of the UI makes you a $tool expert,
but it's how people feel it. With git, 75% of the commands (and
don't get me started with the options ;P) is a _lot_. bzr is way
better at that game: there are at least as many commands, but those
are completely hidden to the user.
Of course having our guts easy to grok and find is a big advantage
for the git gurus. But for the newcomer it's a disconcerting.
There is probably more things I'd change, but those were the first UI
rumblings from me :)
--
·O· Pierre Habouzit
··O madcoder@debian.org
OOO http://www.madism.org
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [RFC] best way to show diff of commit
From: Junio C Hamano @ 2007-11-25 22:27 UTC (permalink / raw)
To: Pierre Habouzit; +Cc: J. Bruce Fields, Git ML
In-Reply-To: <20071125220902.GB21121@artemis.corp>
Pierre Habouzit <madcoder@debian.org> writes:
> Hmm it doesn't because I would have to call git commit -v each time I
> commit and well I _like_ having the status better. And moreover I want
> the diff to go in a separated buffer too.
I've never felt it a problem while editing the log message in Emacs.
Don't enhanced vi implementations let you split the same buffer into
two allowing you to view different portions of it these days?
^ permalink raw reply
* [PATCH] Use is_absolute_path() in diff-lib.c, lockfile.c, setup.c, trace.c
From: Steffen Prohaska @ 2007-11-25 22:29 UTC (permalink / raw)
To: git; +Cc: Steffen Prohaska
Using the helper function to test for absolute paths makes porting easier.
Signed-off-by: Steffen Prohaska <prohaska@zib.de>
---
diff-lib.c | 2 +-
lockfile.c | 2 +-
setup.c | 2 +-
trace.c | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
BTW, what happend to the msysgit related patches:
[PATCH 1/3] sha1_file.c: Fix size_t related printf format warnings
[PATCH 2/3] builtin-init-db: use get_git_dir() instead of getenv()
I never received comments about them, nor do I find them on pu.
Steffen
diff --git a/diff-lib.c b/diff-lib.c
index f8e936a..d85d8f3 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -231,7 +231,7 @@ static int handle_diff_files_args(struct rev_info *revs,
static int is_outside_repo(const char *path, int nongit, const char *prefix)
{
int i;
- if (nongit || !strcmp(path, "-") || path[0] == '/')
+ if (nongit || !strcmp(path, "-") || is_absolute_path(path))
return 1;
if (prefixcmp(path, "../"))
return 0;
diff --git a/lockfile.c b/lockfile.c
index 258fb3f..f45d3ed 100644
--- a/lockfile.c
+++ b/lockfile.c
@@ -94,7 +94,7 @@ static char *resolve_symlink(char *p, size_t s)
return p;
}
- if (link[0] == '/') {
+ if (is_absolute_path(link)) {
/* absolute path simply replaces p */
if (link_len < s)
strcpy(p, link);
diff --git a/setup.c b/setup.c
index 43cd3f9..2c7b5cb 100644
--- a/setup.c
+++ b/setup.c
@@ -59,7 +59,7 @@ const char *prefix_path(const char *prefix, int len, const char *path)
const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
{
static char path[PATH_MAX];
- if (!pfx || !*pfx || arg[0] == '/')
+ if (!pfx || !*pfx || is_absolute_path(arg))
return arg;
memcpy(path, pfx, pfx_len);
strcpy(path + pfx_len, arg);
diff --git a/trace.c b/trace.c
index 0d89dbe..d3d1b6d 100644
--- a/trace.c
+++ b/trace.c
@@ -37,7 +37,7 @@ static int get_trace_fd(int *need_close)
return STDERR_FILENO;
if (strlen(trace) == 1 && isdigit(*trace))
return atoi(trace);
- if (*trace == '/') {
+ if (is_absolute_path(trace)) {
int fd = open(trace, O_WRONLY | O_APPEND | O_CREAT, 0666);
if (fd == -1) {
fprintf(stderr,
--
1.5.3.6.878.g8c9e2
^ permalink raw reply related
* Re: [Resend Trivial PATCH] For the sake of correctness, fix file descriptor leak.
From: Junio C Hamano @ 2007-11-25 22:29 UTC (permalink / raw)
To: André Goddard Rosa; +Cc: Git Mailing List
In-Reply-To: <b8bf37780711251337q41e02304q8fd2654b1e83201@mail.gmail.com>
The codepath you are touching will exit immediately after an error
return; I do not feel much urgency to it, although I do not think the
patch would _hurt_.
Please follow the established convention for patch submission (see
patches on the list from other people as examples).
^ permalink raw reply
* Re: [RFC] best way to show diff of commit
From: Pierre Habouzit @ 2007-11-25 22:31 UTC (permalink / raw)
To: Junio C Hamano; +Cc: J. Bruce Fields, Git ML
In-Reply-To: <7vfxyuj70i.fsf@gitster.siamese.dyndns.org>
[-- Attachment #1: Type: text/plain, Size: 1012 bytes --]
On Sun, Nov 25, 2007 at 10:27:09PM +0000, Junio C Hamano wrote:
> Pierre Habouzit <madcoder@debian.org> writes:
>
> > Hmm it doesn't because I would have to call git commit -v each time I
> > commit and well I _like_ having the status better. And moreover I want
> > the diff to go in a separated buffer too.
>
> I've never felt it a problem while editing the log message in Emacs.
>
> Don't enhanced vi implementations let you split the same buffer into
> two allowing you to view different portions of it these days?
Well, maybe I could write my plugin so that it cuts the diff out from
the main buffer indeed, though I will have to learn using git commit -v
instead of git commit :P
That and the fact that the syntax colorization of the diff doesn't
work, but it's probably not up to git to fix that.
--
·O· Pierre Habouzit
··O madcoder@debian.org
OOO http://www.madism.org
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: What's cooking in git.git (topics)
From: Junio C Hamano @ 2007-11-25 22:42 UTC (permalink / raw)
To: J. Bruce Fields; +Cc: Nicolas Pitre, Jeff King, Johannes Schindelin, git
In-Reply-To: <20071125215128.GC23820@fieldses.org>
"J. Bruce Fields" <bfields@fieldses.org> writes:
> Anyway, here's a first draft.
>
> --b.
>
> diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt
> index 8355cce..7544715 100644
> --- a/Documentation/user-manual.txt
> +++ b/Documentation/user-manual.txt
> ...
> +Normally whenever a branch head in a public repository is modified, it
> +is modified to point to a descendent of the commit that it pointed to
> +before. By forcing a push in this situation, you break that convention.
> +(See <<problems-with-rewriting-history>>).
> +
> +Nevertheless, this is a common practice for people that need a simple
> +way to publish a work-in-progress patch series, and it is an acceptable
> +compromise as long as you warn other developers that this is how you
> +intend to manage the branch.
Note that modern git allows repository owners to forbid such a forced
non fast forward push at the receiving end. In such a case, you cannot
even force a push.
Instead, you would need to fetch the current branch tip from the remote
and merge it into the branch you were tring to push, possibly using the
"ours" merge strategy, before pushing it again. Use of "ours" merge in
such a case:
- makes the next fetch by other people properly fast-forwarding;
- records your admission of guilt: "I screwed up the last push and
this is a replacement --- this is what I really should have pushed
the last time".
- makes the resulting tree exactly the same as what you tried to push
unsuccessfully. This is a valid substitute to a forced push in that
it reverts the mistakes _you_ made with the previous push.
^ permalink raw reply
* Re: [RFC] best way to show diff of commit
From: Junio C Hamano @ 2007-11-25 22:52 UTC (permalink / raw)
To: Pierre Habouzit; +Cc: J. Bruce Fields, Git ML
In-Reply-To: <20071125223150.GD21121@artemis.corp>
Pierre Habouzit <madcoder@debian.org> writes:
> On Sun, Nov 25, 2007 at 10:27:09PM +0000, Junio C Hamano wrote:
>> Pierre Habouzit <madcoder@debian.org> writes:
>>
>> > Hmm it doesn't because I would have to call git commit -v each time I
>> > commit and well I _like_ having the status better. And moreover I want
>> > the diff to go in a separated buffer too.
>>
>> I've never felt it a problem while editing the log message in Emacs.
>>
>> Don't enhanced vi implementations let you split the same buffer into
>> two allowing you to view different portions of it these days?
>
> Well, maybe I could write my plugin so that it cuts the diff out from
> the main buffer indeed, though I will have to learn using git commit -v
> instead of git commit :P
>
> That and the fact that the syntax colorization of the diff doesn't
> work, but it's probably not up to git to fix that.
Or you can use pre-commit hook (which will be run with GIT_INDEX_FILE
set to the index file used for the commit) to generate the diff in a
separate file, and set EDITOR (or GIT_EDITOR) to a script around vim to
open the given COMMIT_EDITMSG as well as that file you create.
^ permalink raw reply
* Re: What's cooking in git.git (topics)
From: J. Bruce Fields @ 2007-11-25 23:08 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Nicolas Pitre, Jeff King, Johannes Schindelin, git
In-Reply-To: <7v63zqj6bj.fsf@gitster.siamese.dyndns.org>
On Sun, Nov 25, 2007 at 02:42:08PM -0800, Junio C Hamano wrote:
> "J. Bruce Fields" <bfields@fieldses.org> writes:
>
> > Anyway, here's a first draft.
> >
> > --b.
> >
> > diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt
> > index 8355cce..7544715 100644
> > --- a/Documentation/user-manual.txt
> > +++ b/Documentation/user-manual.txt
> > ...
> > +Normally whenever a branch head in a public repository is modified, it
> > +is modified to point to a descendent of the commit that it pointed to
> > +before. By forcing a push in this situation, you break that convention.
> > +(See <<problems-with-rewriting-history>>).
> > +
> > +Nevertheless, this is a common practice for people that need a simple
> > +way to publish a work-in-progress patch series, and it is an acceptable
> > +compromise as long as you warn other developers that this is how you
> > +intend to manage the branch.
>
> Note that modern git allows repository owners to forbid such a forced
> non fast forward push at the receiving end. In such a case, you cannot
> even force a push.
>
> Instead, you would need to fetch the current branch tip from the remote
> and merge it into the branch you were tring to push, possibly using the
> "ours" merge strategy, before pushing it again. Use of "ours" merge in
> such a case:
>
> - makes the next fetch by other people properly fast-forwarding;
>
> - records your admission of guilt: "I screwed up the last push and
> this is a replacement --- this is what I really should have pushed
> the last time".
>
> - makes the resulting tree exactly the same as what you tried to push
> unsuccessfully. This is a valid substitute to a forced push in that
> it reverts the mistakes _you_ made with the previous push.
OK, that's interesting. In a similar vein, I've been experimenting with
"merge -s ours" lately as a way to keep track of the "meta-history" of
an unsubmitted patch series in progress. It seems a little hairy right
now, but maybe it'll turn out to be The Right Thing to do.
I don't want to deal with this in the manual yet. For the sake of
keeping things simple, I'd rather first stick to the case of a public
repository set up by the user which the user controls. And I think that
kind of use of "-s ours" is worth documenting but I'm not sure how to
deal with it yet.
--b.
^ 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