* Re: [PATCH 3/3] update a few Porcelain-ish for ref lock safety.
From: Andy Whitcroft @ 2006-09-26 18:08 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vu02uqzaj.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano wrote:
> This updates the use of git-update-ref in git-branch, git-tag
> and git-commit to make them safer in a few corner cases as
> demonstration.
>
> - git-tag makes sure that the named tag does not exist, allows
> you to edit tag message and then creates the tag. If a tag
> with the same name was created by somebody else in the
> meantime, it used to happily overwrote it. Now it notices
> the situation.
>
> - git-branch -d and git-commit (for the initial commit) had the
> same issue but with smaller race window, which is plugged
> with this.
>
> Signed-off-by: Junio C Hamano <junkio@cox.net>
> ---
>
> * Obviously I would need to update this on top of Linus's
> packed-refs, but this 3-patch series applies on top of the
> current "master".
>
> git-branch.sh | 9 ++++++---
> git-commit.sh | 2 +-
> git-tag.sh | 9 ++++++---
> 3 files changed, 13 insertions(+), 7 deletions(-)
>
> diff --git a/git-branch.sh b/git-branch.sh
> index e0501ec..2b58d20 100755
> --- a/git-branch.sh
> +++ b/git-branch.sh
> @@ -42,8 +42,7 @@ If you are sure you want to delete it, r
> esac
> ;;
> esac
> - rm -f "$GIT_DIR/logs/refs/heads/$branch_name"
> - rm -f "$GIT_DIR/refs/heads/$branch_name"
> + git update-ref -d "refs/heads/$branch_name" "$branch"
> echo "Deleted branch $branch_name."
> done
> exit 0
> @@ -112,6 +111,7 @@ rev=$(git-rev-parse --verify "$head") ||
> git-check-ref-format "heads/$branchname" ||
> die "we do not like '$branchname' as a branch name."
>
> +prev=0000000000000000000000000000000000000000
> if [ -e "$GIT_DIR/refs/heads/$branchname" ]
> then
> if test '' = "$force"
> @@ -121,10 +121,13 @@ then
> then
> die "cannot force-update the current branch."
> fi
> + prev=`git rev-parse --verify "refs/heads/$branchname"`
> fi
> if test "$create_log" = 'yes'
> then
> mkdir -p $(dirname "$GIT_DIR/logs/refs/heads/$branchname")
> touch "$GIT_DIR/logs/refs/heads/$branchname"
> fi
> -git update-ref -m "branch: Created from $head" "refs/heads/$branchname" $rev
> +git update-ref -m "branch: Created from $head" \
> + "refs/heads/$branchname" $rev $prev
> +
> diff --git a/git-commit.sh b/git-commit.sh
> index 5a4c659..87b13ef 100755
> --- a/git-commit.sh
> +++ b/git-commit.sh
> @@ -554,8 +554,8 @@ else
> exit 1
> fi
> PARENTS=""
> - current=
> rloga='commit (initial)'
> + current=0000000000000000000000000000000000000000
> fi
>
> if test -z "$no_edit"
> diff --git a/git-tag.sh b/git-tag.sh
> index a0afa25..2bde3c0 100755
> --- a/git-tag.sh
> +++ b/git-tag.sh
> @@ -63,8 +63,11 @@ done
>
> name="$1"
> [ "$name" ] || usage
> -if [ -e "$GIT_DIR/refs/tags/$name" -a -z "$force" ]; then
> - die "tag '$name' already exists"
> +prev=0000000000000000000000000000000000000000
It seems a little odd to need to use such a large 'none' thing. Will
linus' updates start returning this when there is no tag? If so then it
makes sense. Else perhaps it would be nice to have a short cut for it.
Such as 'none'.
-apw
^ permalink raw reply
* git packing leaves unpacked files
From: Andy Whitcroft @ 2006-09-26 18:04 UTC (permalink / raw)
To: Git Mailing List
I was just looking at my kernel repository and noticed that even after a
git repack -a -d I have some loose files. A quick look at repack
doesn't seem to explain why some are either not packed or are kept unpacked.
Is this something I should be expecting?
-apw
^ permalink raw reply
* [PATCH 3/3] update a few Porcelain-ish for ref lock safety.
From: Junio C Hamano @ 2006-09-26 18:05 UTC (permalink / raw)
To: git
In-Reply-To: <7vmz8o1em0.fsf_-_@assigned-by-dhcp.cox.net>
This updates the use of git-update-ref in git-branch, git-tag
and git-commit to make them safer in a few corner cases as
demonstration.
- git-tag makes sure that the named tag does not exist, allows
you to edit tag message and then creates the tag. If a tag
with the same name was created by somebody else in the
meantime, it used to happily overwrote it. Now it notices
the situation.
- git-branch -d and git-commit (for the initial commit) had the
same issue but with smaller race window, which is plugged
with this.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
* Obviously I would need to update this on top of Linus's
packed-refs, but this 3-patch series applies on top of the
current "master".
git-branch.sh | 9 ++++++---
git-commit.sh | 2 +-
git-tag.sh | 9 ++++++---
3 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/git-branch.sh b/git-branch.sh
index e0501ec..2b58d20 100755
--- a/git-branch.sh
+++ b/git-branch.sh
@@ -42,8 +42,7 @@ If you are sure you want to delete it, r
esac
;;
esac
- rm -f "$GIT_DIR/logs/refs/heads/$branch_name"
- rm -f "$GIT_DIR/refs/heads/$branch_name"
+ git update-ref -d "refs/heads/$branch_name" "$branch"
echo "Deleted branch $branch_name."
done
exit 0
@@ -112,6 +111,7 @@ rev=$(git-rev-parse --verify "$head") ||
git-check-ref-format "heads/$branchname" ||
die "we do not like '$branchname' as a branch name."
+prev=0000000000000000000000000000000000000000
if [ -e "$GIT_DIR/refs/heads/$branchname" ]
then
if test '' = "$force"
@@ -121,10 +121,13 @@ then
then
die "cannot force-update the current branch."
fi
+ prev=`git rev-parse --verify "refs/heads/$branchname"`
fi
if test "$create_log" = 'yes'
then
mkdir -p $(dirname "$GIT_DIR/logs/refs/heads/$branchname")
touch "$GIT_DIR/logs/refs/heads/$branchname"
fi
-git update-ref -m "branch: Created from $head" "refs/heads/$branchname" $rev
+git update-ref -m "branch: Created from $head" \
+ "refs/heads/$branchname" $rev $prev
+
diff --git a/git-commit.sh b/git-commit.sh
index 5a4c659..87b13ef 100755
--- a/git-commit.sh
+++ b/git-commit.sh
@@ -554,8 +554,8 @@ else
exit 1
fi
PARENTS=""
- current=
rloga='commit (initial)'
+ current=0000000000000000000000000000000000000000
fi
if test -z "$no_edit"
diff --git a/git-tag.sh b/git-tag.sh
index a0afa25..2bde3c0 100755
--- a/git-tag.sh
+++ b/git-tag.sh
@@ -63,8 +63,11 @@ done
name="$1"
[ "$name" ] || usage
-if [ -e "$GIT_DIR/refs/tags/$name" -a -z "$force" ]; then
- die "tag '$name' already exists"
+prev=0000000000000000000000000000000000000000
+if test -e "$GIT_DIR/refs/tags/$name"
+then
+ test -n "$force" || die "tag '$name' already exists"
+ prev=`git rev-parse "refs/tags/$name"`
fi
shift
git-check-ref-format "tags/$name" ||
@@ -109,4 +112,4 @@ fi
leading=`expr "refs/tags/$name" : '\(.*\)/'` &&
mkdir -p "$GIT_DIR/$leading" &&
-echo $object > "$GIT_DIR/refs/tags/$name"
+GIT_DIR="$GIT_DIR" git update-ref "refs/tags/$name" "$object" "$prev"
--
1.4.2.1.g7a39b
^ permalink raw reply related
* Notes on Using Git with Subprojects
From: A Large Angry SCM @ 2006-09-26 17:40 UTC (permalink / raw)
To: git
20060926.1715
Notes on Using Git with Subprojects
===================================
Copyright (C) 2006 by Raymond S Brand
Git does not have native support for subprojects and this is a good
thing because managing subprojects is better handled by the project
build machinery. Managing subprojects with the project build machinery
is more flexible than the native support from an SCM and allows the use
of different SCMs by different subprojects. However, there is a lot of
interest in using Git for the SCM of a project with subprojects.
Git, unfortunately, does not make it easy. What is wanted is to put all
of the subprojects in one repository and be able to checkout the various
parts from a local copy of the repository. The problem is, with Git, a
repository can have at most one working directory associated with it at
a time. This is because Git stores a lot of information about the
contents of the working directory in the repository. In fact, the usual
situation is that the repository, itself, is in the working directory.
This note describes a method to use Git with subprojects; other methods
are also possible.
Definitions
-----------
Parent Project:
A project that logically contains one or more subprojects.
Project:
A set of files that is (relatively) self contained with respect
to changes and treated as a unit by the SCM.
Root Project:
A project that is not a subproject.
Subproject:
A project logically contained in another project.
Setup
-----
All subprojects are contained in a single repository and referred to by
separate branches in $GIT_DIR/refs/heads/. Developers create a local
copy of the project repository; hereafter, referred to as the "local
master repository" or just "local master". All fetches, pulls and pushes
by the developers with the "local master" of other developers should be
to and from their own "local master".
Root Project Checkout
---------------------
The root project is the project that all of the subprojects are a part
of. It is a parent project of one or more subprojects; each of which can
also be parent projects to other subprojects.
To checkout the root project, choose an name for the project working
directory (the working directory must not already exist) and perform the
equivalent of the following commands.
git-clone -s -n $LOCAL_MASTER $ROOT_DIR \
&& cd $ROOT_DIR \
&& git-checkout -b $ROOT_BRANCH--local $ROOT_BRANCH
Where:
$LOCAL_MASTER is the path to the "local master"
$ROOT_DIR is the name of the working directory to use
$ROOT_BRANCH is the branch name of the root project
$ROOT_BRANCH--local is a branch for local changes
This will leave the current working directory of the shell in the
project working directory.
This also creates a branch with the suffix of "--local" to hold all of
the local working directory commits and modifications. The $ROOT_BRANCH
is used as a tracking branch so that upstream changes can be fetched
into the working repository without affecting the checked out files.
Once the root project is checked out, the subprojects are checked out.
Subproject Checkout
-------------------
Each project that is a parent project needs to checkout all of the
subprojects of the project. Each subproject is checked out with the
equivalent of the following bash commands:
git-clone -s -n $LOCAL_MASTER $SUBPROJECT_DIR \
&& ( cd $SUBPROJECT_DIR \
&& git-checkout -b $SUBPROJECT_BRANCH--local \
$SUBPROJECT_BRANCH
)
Where:
$LOCAL_MASTER is the path to the "local master"
$SUBPROJECT_DIR is the directory name of the subproject
$SUBPROJECT_BRANCH is the branch name of the subproject
$SUBPROJECT_BRANCH--local is a branch for local changes
If a subproject has subprojects, then the checkouts need to done
recursively. With suitable project/subproject/branch naming conventions
this can easily automated.
Project Development
-------------------
Changes to a project are performed in the working directory of the
project and are recorded in the repository in the working directory on
the $PROJECT--local branch.
Receiving Project Upstream Changes
----------------------------------
Upstream project changes are first fetched into the project tracking
branch of the local master repository and are then fetched into the
project tracking branch of the working directory repositories. To merge
upstream changes into the working directory, a pull from the project
tracking branch of the working directory repository executed.
# Fetch project branch from upstream to local master
(cd $LOCAL_MASTER && git-fetch $UPSTREAM $PROJECT_BRANCH)
# Fetch project branch from local master to working repo
git-fetch $LOCAL_MASTER $PROJECT_BRANCH
# Merge upstream changes in to working directory
git-pull --no-commit . $PROJECT_BRANCH
Where:
$LOCAL_MASTER is the path to the "local master"
$UPSTREAM is the Git URL of the upstream repository
$PROJECT_BRANCH is the branch name of the (sub)project
Sending Project Changes Upstream
--------------------------------
To send project changes upstream from a working directory repository,
the changes are first pushed to a branch in the local master repository,
$PROJECT--$IDENT. The changes can then be pushed or pulled from the
local master repository.
# Push project changes to local master
git-push $LOCAL_MASTER \
$PROJECT_BRANCH--local:$PROJECT_BRANCH--$IDENT
# Push project changes from local master to upstream
(cd $LOCAL_MASTER && git-push $UPSTREAM \
$PROJECT_BRANCH--$IDENT:$PROJECT_BRANCH--$NICK--$IDENT)
Where:
$LOCAL_MASTER is the path to the "local master"
$UPSTREAM is the Git URL of the upstream repository
$PROJECT_BRANCH is the branch name of the (sub)project
$PROJECT_BRANCH--local is a branch for local changes
$IDENT is a label unique for this set of working directories
$NICK is a (branch name safe) identifier of the developer
Automation
----------
Adding the following example code to the makefiles of the root project
and subprojects with the appropriate information can automate most of
the operations needed to support subprojects with Git. The ProjectSetup
target needs the REPOSITORY and IDENT make variables to be set but the
other targets will use the values saved by the ProjectSetup target.
---->8---- ---->8---- ---->8---- ---->8---- ---->8---- ---->8----
# Add this to the makefiles
PROJECT := branch/name # Relative to $GIT_DIR/refs/heads/
SUBPROJECTS := a/b c/d # Each relative to $GIT_DIR/refs/heads/
include Git_machinery.make
# Rest of the Makefile
---->8---- ---->8---- ---->8---- ---->8---- ---->8---- ---->8----
# Git_machinery.make
include GIT-SUBPROJECT-VARS.make
REFS := /refs/heads/$(REFPREFIX)
GIT-SUBPROJECT-VARS.make:
rm -rf GIT-SUBPROJECT-VARS.make
echo "REPOSITORY := $(REPOSITORY)" > GIT-SUBPROJECT-VARS.make
echo "REFPREFIX := $(REFPREFIX)" >> GIT-SUBPROJECT-VARS.make
echo "IDENT := $(IDENT)" >> GIT-SUBPROJECT-VARS.make
ProjectSetup:: GIT-SUBPROJECT-VARS.make
for SUBPROJECT in $(SUBPROJECTS) ; \
do \
git-clone -s -n $(REPOSITORY) $$(basename $$SUBPROJECT) \
&& ( cd $$(basename $$SUBPROJECT) \
&& git-checkout -b \
$(REFS)$$SUBPROJECT--local $(REFS)$$SUBPROJECT \
&& $(MAKE) ProjectSetup \
) \
done
FetchMaster::
git-fetch $(REPOSITORY) $(REFS)$(PROJECT)
for SUBPROJECT in $(SUBPROJECTS) ; \
do \
$(MAKE) -C $$(basename $$SUBPROJECT) FetchMaster ; \
done
PullMaster::
git-fetch $(REPOSITORY) $(REFS)$(PROJECT)
git-pull --no-commit . $(REFS)$(PROJECT)
for SUBPROJECT in $(SUBPROJECTS) ; \
do \
$(MAKE) -C $$(basename $$SUBPROJECT) PullMaster ; \
done
PushMaster::
git-push $(REPOSITORY) \
$(REFS)$(PROJECT)--local:$(REFS)$(PROJECT)--$(IDENT)
for SUBPROJECT in $(SUBPROJECTS) ; \
do \
$(MAKE) -C $$(basename $$SUBPROJECT) PushMaster ; \
done
---->8---- ---->8---- ---->8---- ---->8---- ---->8---- ---->8----
The example Makefile code has some limitations: There is no error
checking. It does not handle subprojects rooted in a non top level
directory of the parent project. There are other Git commands that can
be usefully applied recursively to all subprojects.
^ permalink raw reply
* Re: [PATCH] gitweb: tree view: eliminate redundant "blob"
From: Luben Tuikov @ 2006-09-26 17:04 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vhcyvrvab.fsf@assigned-by-dhcp.cox.net>
--- Junio C Hamano <junkio@cox.net> wrote:
> Luben Tuikov <ltuikov@yahoo.com> writes:
>
> > Binary and non-binary blobs:
> >
> > The "list" table element of tree view is identical
> > to the "blob" link part of the link table element.
> > I.e. clicking on "blob" is identical to clicking on
> > the entry itself.
>
> Then perhaps we can lose tree link for the same reasoning?
Indeed, I think so too.
Luben
^ permalink raw reply
* Re: [PATCH] gitweb: tree view: eliminate redundant "blob"
From: Jakub Narebski @ 2006-09-26 16:24 UTC (permalink / raw)
To: git
In-Reply-To: <20060926160729.GH20017@pasky.or.cz>
Petr Baudis wrote:
> Dear diary, on Tue, Sep 26, 2006 at 10:54:49AM CEST, I got a letter
> where Jakub Narebski <jnareb@gmail.com> said that...
>> I'd rather not. The fact that the file name and tree name is link,
>> and the fact that commit title and tag title is link is a _convenience_.
>> Not always it is visible (without mouseover) that it is link.
>> And it is _not_ visible in the case of files!
>
> Then that should be fixed.
>
> And directories should have trailing slash in their name in the tree
> listing, for people with non-UNIX background who don't understand the
> ls -l like output.
Something like ls -lF format? Currently directories differs visibly
from file entries, because directory entries are visibly links. One
single slash at the end is much less visible than change of color and
underline.
Besides "blob" link for files and "tree" link for directories states
explicitely the kind of view. List entry link states this implicitely.
I'd rather like the redundancy.
>> And for example for commits and heads there are two possible
>> views, commit and commitdiff for commit, shortlog and log for head,
>> of which we arbitrary chose one for the subject link. So in that
>> case the additional self link is needed. I'd rather have both.
>
> For commits and heads, I agree. But that's not what this patch does.
What this patch does is introduce inconsistency. Even if you agree
to treat commits and heads specially, it treats directory entries
differently from file entries; and differently from tag entries
(where tag objects have the same duplication) in tags view. In tags
view on one hand it clearly distiguish lightweight from "heavyweight"
tags (even heavyweight tags without tag message), on the other
"tag | tag ..." for tag pointing to tag is quite strange.
>> And for consistency I'd rather always have visible form default
>> self link/
>
> A parse error kicked me off here, sorry.
I'd rather always have the link which is in "list" entry stated
also explicitely.
> (I'm personally kind of ambivalent to the change.)
There are many other changes which should be rather done, like for
example remotes/ support.
--
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
^ permalink raw reply
* Re: [PATCH] gitweb: tree view: eliminate redundant "blob"
From: Petr Baudis @ 2006-09-26 16:07 UTC (permalink / raw)
To: Jakub Narebski; +Cc: git
In-Reply-To: <efapsl$e65$1@sea.gmane.org>
Dear diary, on Tue, Sep 26, 2006 at 10:54:49AM CEST, I got a letter
where Jakub Narebski <jnareb@gmail.com> said that...
> I'd rather not. The fact that the file name and tree name is link,
> and the fact that commit title and tag title is link is a _convenience_.
> Not always it is visible (without mouseover) that it is link.
> And it is _not_ visible in the case of files!
Then that should be fixed.
And directories should have trailing slash in their name in the tree
listing, for people with non-UNIX background who don't understand the
ls -l like output.
> And for example for commits and heads there are two possible
> views, commit and commitdiff for commit, shortlog and log for head,
> of which we arbitrary chose one for the subject link. So in that
> case the additional self link is needed. I'd rather have both.
For commits and heads, I agree. But that's not what this patch does.
> And for consistency I'd rather always have visible form default
> self link/
A parse error kicked me off here, sorry.
(I'm personally kind of ambivalent to the change.)
--
Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
#!/bin/perl -sp0777i<X+d*lMLa^*lN%0]dsXx++lMlN/dsM0<j]dsj
$/=unpack('H*',$_);$_=`echo 16dio\U$k"SK$/SM$n\EsN0p[lN*1
lK[d2%Sa2/d0$^Ixp"|dc`;s/\W//g;$_=pack('H*',/((..)*)$/)
^ permalink raw reply
* [PATCH] gitk: add some key-bind
From: OGAWA Hirofumi @ 2006-09-26 15:27 UTC (permalink / raw)
To: Paul Mackerras; +Cc: git, Junio C Hamano
In-Reply-To: <873bae3b5x.fsf_-_@duaron.myhome.or.jp>
This add initial user of prevfile(), and additional some key-binds for
emacs users.
Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
---
gitk | 6 ++++++
1 file changed, 6 insertions(+)
diff -puN gitk~gitk-key-emacs gitk
--- git/gitk~gitk-key-emacs 2006-09-27 00:17:31.000000000 +0900
+++ git-hirofumi/gitk 2006-09-27 00:17:31.000000000 +0900
@@ -672,6 +672,10 @@ proc makewindow {} {
bind . <Control-Key-Down> "allcanvs yview scroll 1 units"
bind . <Control-Key-Prior> "allcanvs yview scroll -1 pages"
bind . <Control-Key-Next> "allcanvs yview scroll 1 pages"
+ bind . <Control-p> "$ctext yview scroll -1 units"
+ bind . <Control-n> "$ctext yview scroll 1 units"
+ bind . <Alt-v> "$ctext yview scroll -1 pages"
+ bind . <Control-v> "$ctext yview scroll 1 pages"
bindkey <Key-Delete> "$ctext yview scroll -1 pages"
bindkey <Key-BackSpace> "$ctext yview scroll -1 pages"
bindkey <Key-space> "$ctext yview scroll 1 pages"
@@ -690,6 +694,8 @@ proc makewindow {} {
bindkey <Key-Return> {findnext 0}
bindkey ? findprev
bindkey f nextfile
+ bindkey P prevfile
+ bindkey N nextfile
bind . <Control-q> doquit
bind . <Control-f> dofind
bind . <Control-g> {findnext 0}
_
^ permalink raw reply
* [PATCH 8/6] let the GIT native protocol use offsets to delta base when possible
From: Nicolas Pitre @ 2006-09-26 15:27 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
There is no reason not to always do this when both ends agree.
Therefore a client that can accept offsets to delta base always sends
the "ofs-delta" flag. The server will stream a pack with or without
offset to delta base depending on whether that flag is provided or not
with no additional cost.
Signed-off-by: Nicolas Pitre <nico@cam.org>
---
Yeah... 8th of 6 should mean this is pretty much over now.
Since this depends on support that has been merged into the pu branch I
diffed this against pu.
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
diff --git a/fetch-pack.c b/fetch-pack.c
index 99ac08b..90b7940 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -166,12 +166,13 @@ static int find_common(int fd[2], unsign
}
if (!fetching)
- packet_write(fd[1], "want %s%s%s%s%s\n",
+ packet_write(fd[1], "want %s%s%s%s%s%s\n",
sha1_to_hex(remote),
(multi_ack ? " multi_ack" : ""),
(use_sideband == 2 ? " side-band-64k" : ""),
(use_sideband == 1 ? " side-band" : ""),
- (use_thin_pack ? " thin-pack" : ""));
+ (use_thin_pack ? " thin-pack" : ""),
+ " ofs-delta");
else
packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
fetching++;
diff --git a/upload-pack.c b/upload-pack.c
index 4e53edd..4572fff 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -22,7 +22,7 @@ #define REACHABLE (1u << 15)
static unsigned long oldest_have;
static int multi_ack, nr_our_refs;
-static int use_thin_pack;
+static int use_thin_pack, use_ofs_delta;
static struct object_array have_obj;
static struct object_array want_obj;
static unsigned int timeout;
@@ -143,7 +143,9 @@ static void create_pack_file(void)
close(pu_pipe[1]);
close(pe_pipe[0]);
close(pe_pipe[1]);
- execl_git_cmd("pack-objects", "--stdout", "--progress", NULL);
+ execl_git_cmd("pack-objects", "--stdout", "--progress",
+ use_ofs_delta ? "--delta-base-offset" : NULL,
+ NULL);
kill(pid_rev_list, SIGKILL);
die("git-upload-pack: unable to exec git-pack-objects");
}
@@ -476,6 +478,8 @@ static void receive_needs(void)
multi_ack = 1;
if (strstr(line+45, "thin-pack"))
use_thin_pack = 1;
+ if (strstr(line+45, "ofs-delta"))
+ use_ofs_delta = 1;
if (strstr(line+45, "side-band-64k"))
use_sideband = LARGE_PACKET_MAX;
else if (strstr(line+45, "side-band"))
@@ -501,7 +505,7 @@ static void receive_needs(void)
static int send_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
{
- static const char *capabilities = "multi_ack thin-pack side-band side-band-64k";
+ static const char *capabilities = "multi_ack thin-pack side-band side-band-64k ofs-delta";
struct object *o = parse_object(sha1);
if (!o)
^ permalink raw reply related
* [PATCH] gitk: Fix nextfile() and add prevfile()
From: OGAWA Hirofumi @ 2006-09-26 15:22 UTC (permalink / raw)
To: Paul Mackerras; +Cc: git, Junio C Hamano
In-Reply-To: <7vpsdjryj2.fsf@assigned-by-dhcp.cox.net>
The current nextfile() jumps to last hunk, but I think this is not
intention, probably, it's forgetting to add "break;". And this
patch also adds prevfile(), it jumps to previous hunk.
Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
---
gitk | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff -puN gitk~gitk-nextfile-fix gitk
--- git/gitk~gitk-nextfile-fix 2006-09-27 00:16:11.000000000 +0900
+++ git-hirofumi/gitk 2006-09-27 00:16:48.000000000 +0900
@@ -4440,12 +4440,26 @@ proc getblobdiffline {bdf ids} {
}
}
+proc prevfile {} {
+ global difffilestart ctext
+ set prev [lindex $difffilestart 0]
+ set here [$ctext index @0,0]
+ foreach loc $difffilestart {
+ if {[$ctext compare $loc >= $here]} {
+ $ctext yview $prev
+ break
+ }
+ set prev $loc
+ }
+}
+
proc nextfile {} {
global difffilestart ctext
set here [$ctext index @0,0]
foreach loc $difffilestart {
if {[$ctext compare $loc > $here]} {
$ctext yview $loc
+ break
}
}
}
_
^ permalink raw reply
* Re: [PATCH] gitk: Fix nextfile() and more
From: OGAWA Hirofumi @ 2006-09-26 15:19 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Paul Mackerras
In-Reply-To: <7vpsdjryj2.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano <junkio@cox.net> writes:
> OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> writes:
>
>> The current nextfile() jumps to last hunk, but I think this is not
>> intention, probably, it's forgetting to add "break;". Right? And this
>> patch also adds prevfile(), it jumps to previous hunk.
>>
>> The following part is just my favorite the key-binds, it doesn't matter.
>>
>> + bind . <Control-p> "$ctext yview scroll -1 units"
>> + bind . <Control-n> "$ctext yview scroll 1 units"
>> + bind . <Alt-v> "$ctext yview scroll -1 pages"
>> + bind . <Control-v> "$ctext yview scroll 1 pages"
>> + bindkey P prevfile
>> + bindkey N nextfile
>>
>> What do you think of this?
>
> . As a patch e-mail, the initial Hi and trailing Thanks add
> additional work for the person who applies patch.
Ok.
> . I do not have preference on the extra bindings. I do not
> speak for Paul, but I suspect he would have liked them in a
> separate patch.
Ok. I'll send patches.
--
OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
^ permalink raw reply
* [PATCH Rev 3] Cleaned up git-daemon virtual hosting support.
From: Jon Loeliger @ 2006-09-26 14:47 UTC (permalink / raw)
To: git
Standardized on lowercase hostnames from client.
Added interpolation values for the IP address, port and
canonical hostname of the server as it is contacted and
named by the client and passed in via the extended args.
Added --listen=host_or_ipaddr option suport. Renamed port
variable as "listen_port" correspondingly as well.
Documented mutual exclusivity of --inetd option with
--user, --group, --listen and --port options.
Added compat/inet_pton.c from Paul Vixie as needed.
Small memory leaks need to be cleaned up still.
Signed-off-by: Jon Loeliger <jdl@jdl.com>
---
Junio,
Let's try again!
Renamed the "--host=" option as "--listen=" per request.
Follow-up patch to fix small leaks to come still.
jdl
Documentation/git-daemon.txt | 45 +++++++--
Makefile | 3 +
compat/inet_pton.c | 220 ++++++++++++++++++++++++++++++++++++++++++
daemon.c | 151 +++++++++++++++++++++++++----
4 files changed, 390 insertions(+), 29 deletions(-)
diff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt
index 87444b4..d562232 100644
--- a/Documentation/git-daemon.txt
+++ b/Documentation/git-daemon.txt
@@ -8,14 +8,15 @@ git-daemon - A really simple server for
SYNOPSIS
--------
[verse]
-'git-daemon' [--verbose] [--syslog] [--inetd | --port=n] [--export-all]
+'git-daemon' [--verbose] [--syslog] [--export-all]
[--timeout=n] [--init-timeout=n] [--strict-paths]
[--base-path=path] [--user-path | --user-path=path]
[--interpolated-path=pathtemplate]
+ [--reuseaddr] [--detach] [--pid-file=file]
[--enable=service] [--disable=service]
[--allow-override=service] [--forbid-override=service]
- [--reuseaddr] [--detach] [--pid-file=file]
- [--user=user [--group=group]] [directory...]
+ [--inetd | [--listen=host_or_ipaddr] [--port=n] [--user=user [--group=group]]
+ [directory...]
DESCRIPTION
-----------
@@ -54,8 +55,12 @@ OPTIONS
--interpolated-path=pathtemplate::
To support virtual hosting, an interpolated path template can be
used to dynamically construct alternate paths. The template
- supports %H for the target hostname as supplied by the client,
- and %D for the absolute path of the named repository.
+ supports %H for the target hostname as supplied by the client but
+ converted to all lowercase, %CH for the canonical hostname,
+ %IP for the server's IP address, %P for the port number,
+ and %D for the absolute path of the named repository.
+ After interpolation, the path is validated against the directory
+ whitelist.
--export-all::
Allow pulling from all directories that look like GIT repositories
@@ -64,9 +69,17 @@ OPTIONS
--inetd::
Have the server run as an inetd service. Implies --syslog.
+ Incompatible with --port, --listen, --user and --group options.
+
+--listen=host_or_ipaddr::
+ Listen on an a specific IP address or hostname. IP addresses can
+ be either an IPv4 address or an IPV6 address if supported. If IPv6
+ is not supported, then --listen=hostname is also not supported and
+ --listen must be given an IPv4 address.
+ Incompatible with '--inetd' option.
---port::
- Listen on an alternative port.
+--port=n::
+ Listen on an alternative port. Incompatible with '--inetd' option.
--init-timeout::
Timeout between the moment the connection is established and the
@@ -182,6 +195,24 @@ clients, a symlink from `/software` into
default repository could be made as well.
+git-daemon as regular daemon for virtual hosts::
+ To set up `git-daemon` as a regular, non-inetd service that
+ handles repositories for multiple virtual hosts based on
+ their IP addresses, start the daemon like this:
++
+------------------------------------------------
+ git-daemon --verbose --export-all
+ --interpolated-path=/pub/%IP/%D
+ /pub/192.168.1.200/software
+ /pub/10.10.220.23/software
+------------------------------------------------
++
+In this example, the root-level directory `/pub` will contain
+a subdirectory for each virtual host IP address supported.
+Repositories can still be accessed by hostname though, assuming
+they correspond to these IP addresses.
+
+
Author
------
Written by Linus Torvalds <torvalds@osdl.org>, YOSHIFUJI Hideaki
diff --git a/Makefile b/Makefile
index 673ba2d..bae4822 100644
--- a/Makefile
+++ b/Makefile
@@ -520,6 +520,9 @@ endif
ifdef NO_INET_NTOP
LIB_OBJS += compat/inet_ntop.o
endif
+ifdef NO_INET_PTON
+ LIB_OBJS += compat/inet_pton.o
+endif
ifdef NO_ICONV
ALL_CFLAGS += -DNO_ICONV
diff --git a/compat/inet_pton.c b/compat/inet_pton.c
new file mode 100644
index 0000000..5704e0d
--- /dev/null
+++ b/compat/inet_pton.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 1996-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifndef NS_INT16SZ
+#define NS_INT16SZ 2
+#endif
+
+#ifndef NS_INADDRSZ
+#define NS_INADDRSZ 4
+#endif
+
+#ifndef NS_IN6ADDRSZ
+#define NS_IN6ADDRSZ 16
+#endif
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static int inet_pton4(const char *src, unsigned char *dst);
+static int inet_pton6(const char *src, unsigned char *dst);
+
+/* int
+ * inet_pton4(src, dst)
+ * like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ * 1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ * does not touch `dst' unless it's returning 1.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton4(const char *src, unsigned char *dst)
+{
+ static const char digits[] = "0123456789";
+ int saw_digit, octets, ch;
+ unsigned char tmp[NS_INADDRSZ], *tp;
+
+ saw_digit = 0;
+ octets = 0;
+ *(tp = tmp) = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr(digits, ch)) != NULL) {
+ unsigned int new = *tp * 10 + (pch - digits);
+
+ if (new > 255)
+ return (0);
+ *tp = new;
+ if (! saw_digit) {
+ if (++octets > 4)
+ return (0);
+ saw_digit = 1;
+ }
+ } else if (ch == '.' && saw_digit) {
+ if (octets == 4)
+ return (0);
+ *++tp = 0;
+ saw_digit = 0;
+ } else
+ return (0);
+ }
+ if (octets < 4)
+ return (0);
+ memcpy(dst, tmp, NS_INADDRSZ);
+ return (1);
+}
+
+/* int
+ * inet_pton6(src, dst)
+ * convert presentation level address to network order binary form.
+ * return:
+ * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ * (1) does not touch `dst' unless it's returning 1.
+ * (2) :: in a full address is silently ignored.
+ * credit:
+ * inspired by Mark Andrews.
+ * author:
+ * Paul Vixie, 1996.
+ */
+
+#ifndef NO_IPV6
+static int
+inet_pton6(const char *src, unsigned char *dst)
+{
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+ const char *xdigits, *curtok;
+ int ch, saw_xdigit;
+ unsigned int val;
+
+ memset((tp = tmp), '\0', NS_IN6ADDRSZ);
+ endp = tp + NS_IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if (*src == ':')
+ if (*++src != ':')
+ return (0);
+ curtok = src;
+ saw_xdigit = 0;
+ val = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+ pch = strchr((xdigits = xdigits_u), ch);
+ if (pch != NULL) {
+ val <<= 4;
+ val |= (pch - xdigits);
+ if (val > 0xffff)
+ return (0);
+ saw_xdigit = 1;
+ continue;
+ }
+ if (ch == ':') {
+ curtok = src;
+ if (!saw_xdigit) {
+ if (colonp)
+ return (0);
+ colonp = tp;
+ continue;
+ }
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (unsigned char) (val >> 8) & 0xff;
+ *tp++ = (unsigned char) val & 0xff;
+ saw_xdigit = 0;
+ val = 0;
+ continue;
+ }
+ if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+ inet_pton4(curtok, tp) > 0) {
+ tp += NS_INADDRSZ;
+ saw_xdigit = 0;
+ break; /* '\0' was seen by inet_pton4(). */
+ }
+ return (0);
+ }
+ if (saw_xdigit) {
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (unsigned char) (val >> 8) & 0xff;
+ *tp++ = (unsigned char) val & 0xff;
+ }
+ if (colonp != NULL) {
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const int n = tp - colonp;
+ int i;
+
+ for (i = 1; i <= n; i++) {
+ endp[- i] = colonp[n - i];
+ colonp[n - i] = 0;
+ }
+ tp = endp;
+ }
+ if (tp != endp)
+ return (0);
+ memcpy(dst, tmp, NS_IN6ADDRSZ);
+ return (1);
+}
+#endif
+
+/* int
+ * isc_net_pton(af, src, dst)
+ * convert from presentation format (which usually means ASCII printable)
+ * to network format (which is usually some kind of binary format).
+ * return:
+ * 1 if the address was valid for the specified address family
+ * 0 if the address wasn't valid (`dst' is untouched in this case)
+ * -1 if some other error occurred (`dst' is untouched in this case, too)
+ * author:
+ * Paul Vixie, 1996.
+ */
+int
+inet_pton(int af, const char *src, void *dst)
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_pton4(src, dst));
+#ifndef NO_IPV6
+ case AF_INET6:
+ return (inet_pton6(src, dst));
+#endif
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+ /* NOTREACHED */
+}
diff --git a/daemon.c b/daemon.c
index ef3a955..260f0cf 100644
--- a/daemon.c
+++ b/daemon.c
@@ -9,6 +9,7 @@ #include <arpa/inet.h>
#include <syslog.h>
#include <pwd.h>
#include <grp.h>
+#include <limits.h>
#include "pkt-line.h"
#include "cache.h"
#include "exec_cmd.h"
@@ -19,13 +20,15 @@ static int verbose;
static int reuseaddr;
static const char daemon_usage[] =
-"git-daemon [--verbose] [--syslog] [--inetd | --port=n] [--export-all]\n"
+"git-daemon [--verbose] [--syslog] [--export-all]\n"
" [--timeout=n] [--init-timeout=n] [--strict-paths]\n"
" [--base-path=path] [--user-path | --user-path=path]\n"
" [--interpolated-path=path]\n"
" [--reuseaddr] [--detach] [--pid-file=file]\n"
" [--[enable|disable|allow-override|forbid-override]=service]\n"
-" [--user=user [[--group=group]] [directory...]";
+" [--inetd | [--listen=host_or_ipaddr] [--port=n]\n"
+" [--user=user [--group=group]]\n"
+" [directory...]";
/* List of acceptable pathname prefixes */
static char **ok_paths;
@@ -56,11 +59,17 @@ static unsigned int init_timeout;
* Feel free to make dynamic as needed.
*/
#define INTERP_SLOT_HOST (0)
-#define INTERP_SLOT_DIR (1)
-#define INTERP_SLOT_PERCENT (2)
+#define INTERP_SLOT_CANON_HOST (1)
+#define INTERP_SLOT_IP (2)
+#define INTERP_SLOT_PORT (3)
+#define INTERP_SLOT_DIR (4)
+#define INTERP_SLOT_PERCENT (5)
static struct interp interp_table[] = {
{ "%H", 0},
+ { "%CH", 0},
+ { "%IP", 0},
+ { "%P", 0},
{ "%D", 0},
{ "%%", "%"},
};
@@ -401,9 +410,17 @@ static void parse_extra_args(char *extra
val = extra_args + 5;
vallen = strlen(val) + 1;
if (*val) {
- char *save = xmalloc(vallen);
+ char *port;
+ char *save = xmalloc(vallen); /* FIXME: Leak */
+
interp_table[INTERP_SLOT_HOST].value = save;
strlcpy(save, val, vallen);
+ port = strrchr(save, ':');
+ if (port) {
+ *port = 0;
+ port++;
+ interp_table[INTERP_SLOT_PORT].value = port;
+ }
}
/* On to the next one */
extra_args = val + vallen;
@@ -411,6 +428,73 @@ static void parse_extra_args(char *extra
}
}
+void fill_in_extra_table_entries(struct interp *itable)
+{
+ char *hp;
+ char *canon_host = NULL;
+ char *ipaddr = NULL;
+
+ /*
+ * Replace literal host with lowercase-ized hostname.
+ */
+ hp = interp_table[INTERP_SLOT_HOST].value;
+ for ( ; *hp; hp++)
+ *hp = tolower(*hp);
+
+ /*
+ * Locate canonical hostname and its IP address.
+ */
+#ifndef NO_IPV6
+ {
+ struct addrinfo hints;
+ struct addrinfo *ai, *ai0;
+ int gai;
+ static char addrbuf[HOST_NAME_MAX + 1];
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+
+ gai = getaddrinfo(interp_table[INTERP_SLOT_HOST].value, 0, &hints, &ai0);
+ if (!gai) {
+ for (ai = ai0; ai; ai = ai->ai_next) {
+ struct sockaddr_in *sin_addr = (void *)ai->ai_addr;
+
+ canon_host = xstrdup(ai->ai_canonname);
+ inet_ntop(AF_INET, &sin_addr->sin_addr,
+ addrbuf, sizeof(addrbuf));
+ ipaddr = addrbuf;
+ break;
+ }
+ freeaddrinfo(ai0);
+ }
+ }
+#else
+ {
+ struct hostent *hent;
+ struct sockaddr_in sa;
+ char **ap;
+ static char addrbuf[HOST_NAME_MAX + 1];
+
+ hent = gethostbyname(interp_table[INTERP_SLOT_HOST].value);
+ canon_host = xstrdup(hent->h_name);
+
+ ap = hent->h_addr_list;
+ memset(&sa, 0, sizeof sa);
+ sa.sin_family = hent->h_addrtype;
+ sa.sin_port = htons(0);
+ memcpy(&sa.sin_addr, *ap, hent->h_length);
+
+ inet_ntop(hent->h_addrtype, &sa.sin_addr,
+ addrbuf, sizeof(addrbuf));
+ ipaddr = addrbuf;
+ }
+#endif
+
+ interp_table[INTERP_SLOT_CANON_HOST].value = canon_host; /* FIXME: Leak */
+ interp_table[INTERP_SLOT_IP].value = xstrdup(ipaddr); /* FIXME: Leak */
+}
+
+
static int execute(struct sockaddr *addr)
{
static char line[1000];
@@ -451,8 +535,10 @@ #endif
if (len && line[len-1] == '\n')
line[--len] = 0;
- if (len != pktlen)
+ if (len != pktlen) {
parse_extra_args(line + len + 1, pktlen - len - 1);
+ fill_in_extra_table_entries(interp_table);
+ }
for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
struct daemon_service *s = &(daemon_service[i]);
@@ -656,23 +742,22 @@ static int set_reuse_addr(int sockfd)
#ifndef NO_IPV6
-static int socksetup(int port, int **socklist_p)
+static int socksetup(char *listen_addr, int listen_port, int **socklist_p)
{
int socknum = 0, *socklist = NULL;
int maxfd = -1;
char pbuf[NI_MAXSERV];
-
struct addrinfo hints, *ai0, *ai;
int gai;
- sprintf(pbuf, "%d", port);
+ sprintf(pbuf, "%d", listen_port);
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
- gai = getaddrinfo(NULL, pbuf, &hints, &ai0);
+ gai = getaddrinfo(listen_addr, pbuf, &hints, &ai0);
if (gai)
die("getaddrinfo() failed: %s\n", gai_strerror(gai));
@@ -726,20 +811,27 @@ #endif
#else /* NO_IPV6 */
-static int socksetup(int port, int **socklist_p)
+static int socksetup(char *lisen_addr, int listen_port, int **socklist_p)
{
struct sockaddr_in sin;
int sockfd;
+ memset(&sin, 0, sizeof sin);
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(listen_port);
+
+ if (listen_addr) {
+ /* Well, host better be an IP address here. */
+ if (inet_pton(AF_INET, listen_addr, &sin.sin_addr.s_addr) <= 0)
+ return 0;
+ } else {
+ sin.sin_addr.s_addr = htonl(INADDR_ANY);
+ }
+
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
return 0;
- memset(&sin, 0, sizeof sin);
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = htonl(INADDR_ANY);
- sin.sin_port = htons(port);
-
if (set_reuse_addr(sockfd)) {
close(sockfd);
return 0;
@@ -848,13 +940,14 @@ static void store_pid(const char *path)
fclose(f);
}
-static int serve(int port, struct passwd *pass, gid_t gid)
+static int serve(char *listen_addr, int listen_port, struct passwd *pass, gid_t gid)
{
int socknum, *socklist;
- socknum = socksetup(port, &socklist);
+ socknum = socksetup(listen_addr, listen_port, &socklist);
if (socknum == 0)
- die("unable to allocate any listen sockets on port %u", port);
+ die("unable to allocate any listen sockets on host %s port %u",
+ listen_addr, listen_port);
if (pass && gid &&
(initgroups(pass->pw_name, gid) || setgid (gid) ||
@@ -866,7 +959,8 @@ static int serve(int port, struct passwd
int main(int argc, char **argv)
{
- int port = DEFAULT_GIT_PORT;
+ int listen_port = 0;
+ char *listen_addr = NULL;
int inetd_mode = 0;
const char *pid_file = NULL, *user_name = NULL, *group_name = NULL;
int detach = 0;
@@ -883,12 +977,20 @@ int main(int argc, char **argv)
for (i = 1; i < argc; i++) {
char *arg = argv[i];
+ if (!strncmp(arg, "--listen=", 9)) {
+ char *p = arg + 9;
+ char *ph = listen_addr = xmalloc(strlen(arg + 9) + 1);
+ while (*p)
+ *ph++ = tolower(*p++);
+ *ph = 0;
+ continue;
+ }
if (!strncmp(arg, "--port=", 7)) {
char *end;
unsigned long n;
n = strtoul(arg+7, &end, 0);
if (arg[7] && !*end) {
- port = n;
+ listen_port = n;
continue;
}
}
@@ -988,6 +1090,11 @@ int main(int argc, char **argv)
if (inetd_mode && (group_name || user_name))
die("--user and --group are incompatible with --inetd");
+ if (inetd_mode && (listen_port || listen_addr))
+ die("--listen= and --port= are incompatible with --inetd");
+ else if (listen_port == 0)
+ listen_port = DEFAULT_GIT_PORT;
+
if (group_name && !user_name)
die("--group supplied without --user");
@@ -1036,5 +1143,5 @@ int main(int argc, char **argv)
if (pid_file)
store_pid(pid_file);
- return serve(port, pass, gid);
+ return serve(listen_addr, listen_port, pass, gid);
}
--
1.4.2.1.g85d8-dirty
^ permalink raw reply related
* [PATCH Rev 2] Cleaned up git-daemon virtual hosting support.
From: Jon Loeliger @ 2006-09-26 14:11 UTC (permalink / raw)
To: git
Er, dammit. I sent the wrong patch.
Totaly ignore the [Rev 2] variant of this patch.
New stuff to follow...
Sorry,
jdl
^ permalink raw reply
* [PATCH Rev 2] Cleaned up git-daemon virtual hosting support.
From: Jon Loeliger @ 2006-09-26 14:04 UTC (permalink / raw)
To: git
Standardized on lowercase hostnames from client.
Added interpolation values for the IP address, Port and
canonical hostname of the server as it is contacted and
named by the client and passed in via the extended args.
Added --listen=host_or_ipaddr option suport. Renamed port
variable as "listen_port" correspondingly as well.
Documented mutual exclusivity of --inetd option with
--user, --group, --host and --port options.
Added compat_inet_pton from Paul Vixie as needed.
Small memory leaks need to be cleaned up still.
Signed-off-by: Jon Loeliger <jdl@jdl.com>
---
Junio,
Renamed the "--host=" option as "--listen=" per request.
Follow-up patch to fix small leaks to come still.
Thanks,
jdl
Documentation/git-daemon.txt | 45 +++++++--
Makefile | 3 +
compat/inet_pton.c | 220 ++++++++++++++++++++++++++++++++++++++++++
daemon.c | 146 ++++++++++++++++++++++++----
4 files changed, 387 insertions(+), 27 deletions(-)
diff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt
index 87444b4..422cc37 100644
--- a/Documentation/git-daemon.txt
+++ b/Documentation/git-daemon.txt
@@ -8,14 +8,15 @@ git-daemon - A really simple server for
SYNOPSIS
--------
[verse]
-'git-daemon' [--verbose] [--syslog] [--inetd | --port=n] [--export-all]
+'git-daemon' [--verbose] [--syslog] [--export-all]
[--timeout=n] [--init-timeout=n] [--strict-paths]
[--base-path=path] [--user-path | --user-path=path]
[--interpolated-path=pathtemplate]
+ [--reuseaddr] [--detach] [--pid-file=file]
[--enable=service] [--disable=service]
[--allow-override=service] [--forbid-override=service]
- [--reuseaddr] [--detach] [--pid-file=file]
- [--user=user [--group=group]] [directory...]
+ [--inetd | [--host=host_or_ipaddr] [--port=n] [--user=user [--group=group]]
+ [directory...]
DESCRIPTION
-----------
@@ -54,8 +55,12 @@ OPTIONS
--interpolated-path=pathtemplate::
To support virtual hosting, an interpolated path template can be
used to dynamically construct alternate paths. The template
- supports %H for the target hostname as supplied by the client,
- and %D for the absolute path of the named repository.
+ supports %H for the target hostname as supplied by the client but
+ converted to all lowercase, %CH for the canonical hostname,
+ %IP for the server's IP address, %P for the port number,
+ and %D for the absolute path of the named repository.
+ After interpolation, the path is validated against the directory
+ whitelist.
--export-all::
Allow pulling from all directories that look like GIT repositories
@@ -64,9 +69,17 @@ OPTIONS
--inetd::
Have the server run as an inetd service. Implies --syslog.
+ Incompatible with --port, --host, --user and --group options.
+
+--host=host_or_ipaddr::
+ Listen on an a specific IP address or hostname. IP addresses can
+ be either an IPv4 address or an IPV6 address if supported. If IPv6
+ is not supported, then --host=hostname is also not supported and
+ --host must be given an IPv4 address.
+ Incompatible with '--inetd' option.
---port::
- Listen on an alternative port.
+--port=n::
+ Listen on an alternative port. Incompatible with '--inetd' option.
--init-timeout::
Timeout between the moment the connection is established and the
@@ -182,6 +195,24 @@ clients, a symlink from `/software` into
default repository could be made as well.
+git-daemon as regular daemon for virtual hosts::
+ To set up `git-daemon` as a regular, non-inetd service that
+ handles repositories for multiple virtual hosts based on
+ their IP addresses, start the daemon like this:
++
+------------------------------------------------
+ git-daemon --verbose --export-all
+ --interpolated-path=/pub/%IP/%D
+ /pub/192.168.1.200/software
+ /pub/10.10.220.23/software
+------------------------------------------------
++
+In this example, the root-level directory `/pub` will contain
+a subdirectory for each virtual host IP address supported.
+Repositories can still be accessed by hostname though, assuming
+they correspond to these IP addresses.
+
+
Author
------
Written by Linus Torvalds <torvalds@osdl.org>, YOSHIFUJI Hideaki
diff --git a/Makefile b/Makefile
index 673ba2d..bae4822 100644
--- a/Makefile
+++ b/Makefile
@@ -520,6 +520,9 @@ endif
ifdef NO_INET_NTOP
LIB_OBJS += compat/inet_ntop.o
endif
+ifdef NO_INET_PTON
+ LIB_OBJS += compat/inet_pton.o
+endif
ifdef NO_ICONV
ALL_CFLAGS += -DNO_ICONV
diff --git a/compat/inet_pton.c b/compat/inet_pton.c
new file mode 100644
index 0000000..5704e0d
--- /dev/null
+++ b/compat/inet_pton.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 1996-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifndef NS_INT16SZ
+#define NS_INT16SZ 2
+#endif
+
+#ifndef NS_INADDRSZ
+#define NS_INADDRSZ 4
+#endif
+
+#ifndef NS_IN6ADDRSZ
+#define NS_IN6ADDRSZ 16
+#endif
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static int inet_pton4(const char *src, unsigned char *dst);
+static int inet_pton6(const char *src, unsigned char *dst);
+
+/* int
+ * inet_pton4(src, dst)
+ * like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ * 1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ * does not touch `dst' unless it's returning 1.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton4(const char *src, unsigned char *dst)
+{
+ static const char digits[] = "0123456789";
+ int saw_digit, octets, ch;
+ unsigned char tmp[NS_INADDRSZ], *tp;
+
+ saw_digit = 0;
+ octets = 0;
+ *(tp = tmp) = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr(digits, ch)) != NULL) {
+ unsigned int new = *tp * 10 + (pch - digits);
+
+ if (new > 255)
+ return (0);
+ *tp = new;
+ if (! saw_digit) {
+ if (++octets > 4)
+ return (0);
+ saw_digit = 1;
+ }
+ } else if (ch == '.' && saw_digit) {
+ if (octets == 4)
+ return (0);
+ *++tp = 0;
+ saw_digit = 0;
+ } else
+ return (0);
+ }
+ if (octets < 4)
+ return (0);
+ memcpy(dst, tmp, NS_INADDRSZ);
+ return (1);
+}
+
+/* int
+ * inet_pton6(src, dst)
+ * convert presentation level address to network order binary form.
+ * return:
+ * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ * (1) does not touch `dst' unless it's returning 1.
+ * (2) :: in a full address is silently ignored.
+ * credit:
+ * inspired by Mark Andrews.
+ * author:
+ * Paul Vixie, 1996.
+ */
+
+#ifndef NO_IPV6
+static int
+inet_pton6(const char *src, unsigned char *dst)
+{
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+ const char *xdigits, *curtok;
+ int ch, saw_xdigit;
+ unsigned int val;
+
+ memset((tp = tmp), '\0', NS_IN6ADDRSZ);
+ endp = tp + NS_IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if (*src == ':')
+ if (*++src != ':')
+ return (0);
+ curtok = src;
+ saw_xdigit = 0;
+ val = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+ pch = strchr((xdigits = xdigits_u), ch);
+ if (pch != NULL) {
+ val <<= 4;
+ val |= (pch - xdigits);
+ if (val > 0xffff)
+ return (0);
+ saw_xdigit = 1;
+ continue;
+ }
+ if (ch == ':') {
+ curtok = src;
+ if (!saw_xdigit) {
+ if (colonp)
+ return (0);
+ colonp = tp;
+ continue;
+ }
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (unsigned char) (val >> 8) & 0xff;
+ *tp++ = (unsigned char) val & 0xff;
+ saw_xdigit = 0;
+ val = 0;
+ continue;
+ }
+ if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+ inet_pton4(curtok, tp) > 0) {
+ tp += NS_INADDRSZ;
+ saw_xdigit = 0;
+ break; /* '\0' was seen by inet_pton4(). */
+ }
+ return (0);
+ }
+ if (saw_xdigit) {
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (unsigned char) (val >> 8) & 0xff;
+ *tp++ = (unsigned char) val & 0xff;
+ }
+ if (colonp != NULL) {
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const int n = tp - colonp;
+ int i;
+
+ for (i = 1; i <= n; i++) {
+ endp[- i] = colonp[n - i];
+ colonp[n - i] = 0;
+ }
+ tp = endp;
+ }
+ if (tp != endp)
+ return (0);
+ memcpy(dst, tmp, NS_IN6ADDRSZ);
+ return (1);
+}
+#endif
+
+/* int
+ * isc_net_pton(af, src, dst)
+ * convert from presentation format (which usually means ASCII printable)
+ * to network format (which is usually some kind of binary format).
+ * return:
+ * 1 if the address was valid for the specified address family
+ * 0 if the address wasn't valid (`dst' is untouched in this case)
+ * -1 if some other error occurred (`dst' is untouched in this case, too)
+ * author:
+ * Paul Vixie, 1996.
+ */
+int
+inet_pton(int af, const char *src, void *dst)
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_pton4(src, dst));
+#ifndef NO_IPV6
+ case AF_INET6:
+ return (inet_pton6(src, dst));
+#endif
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+ /* NOTREACHED */
+}
diff --git a/daemon.c b/daemon.c
index ef3a955..5f01184 100644
--- a/daemon.c
+++ b/daemon.c
@@ -9,6 +9,7 @@ #include <arpa/inet.h>
#include <syslog.h>
#include <pwd.h>
#include <grp.h>
+#include <limits.h>
#include "pkt-line.h"
#include "cache.h"
#include "exec_cmd.h"
@@ -19,13 +20,14 @@ static int verbose;
static int reuseaddr;
static const char daemon_usage[] =
-"git-daemon [--verbose] [--syslog] [--inetd | --port=n] [--export-all]\n"
+"git-daemon [--verbose] [--syslog] [--export-all]\n"
" [--timeout=n] [--init-timeout=n] [--strict-paths]\n"
" [--base-path=path] [--user-path | --user-path=path]\n"
" [--interpolated-path=path]\n"
" [--reuseaddr] [--detach] [--pid-file=file]\n"
" [--[enable|disable|allow-override|forbid-override]=service]\n"
-" [--user=user [[--group=group]] [directory...]";
+" [--inetd | [--host=host_or_ipaddr] [--port=n] [--user=user [--group=group]]\n"
+" [directory...]";
/* List of acceptable pathname prefixes */
static char **ok_paths;
@@ -56,11 +58,17 @@ static unsigned int init_timeout;
* Feel free to make dynamic as needed.
*/
#define INTERP_SLOT_HOST (0)
-#define INTERP_SLOT_DIR (1)
-#define INTERP_SLOT_PERCENT (2)
+#define INTERP_SLOT_CANON_HOST (1)
+#define INTERP_SLOT_IP (2)
+#define INTERP_SLOT_PORT (3)
+#define INTERP_SLOT_DIR (4)
+#define INTERP_SLOT_PERCENT (5)
static struct interp interp_table[] = {
{ "%H", 0},
+ { "%CH", 0},
+ { "%IP", 0},
+ { "%P", 0},
{ "%D", 0},
{ "%%", "%"},
};
@@ -401,9 +409,17 @@ static void parse_extra_args(char *extra
val = extra_args + 5;
vallen = strlen(val) + 1;
if (*val) {
- char *save = xmalloc(vallen);
+ char *port;
+ char *save = xmalloc(vallen); /* FIXME: Leak */
+
interp_table[INTERP_SLOT_HOST].value = save;
strlcpy(save, val, vallen);
+ port = strrchr(save, ':');
+ if (port) {
+ *port = 0;
+ port++;
+ interp_table[INTERP_SLOT_PORT].value = port;
+ }
}
/* On to the next one */
extra_args = val + vallen;
@@ -411,6 +427,73 @@ static void parse_extra_args(char *extra
}
}
+void fill_in_extra_table_entries(struct interp *itable)
+{
+ char *hp;
+ char *canon_host = NULL;
+ char *ipaddr = NULL;
+
+ /*
+ * Replace literal host with lowercase-ized hostname.
+ */
+ hp = interp_table[INTERP_SLOT_HOST].value;
+ for ( ; *hp; hp++)
+ *hp = tolower(*hp);
+
+ /*
+ * Locate canonical hostname and its IP address.
+ */
+#ifndef NO_IPV6
+ {
+ struct addrinfo hints;
+ struct addrinfo *ai, *ai0;
+ int gai;
+ static char addrbuf[HOST_NAME_MAX + 1];
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+
+ gai = getaddrinfo(interp_table[INTERP_SLOT_HOST].value, 0, &hints, &ai0);
+ if (!gai) {
+ for (ai = ai0; ai; ai = ai->ai_next) {
+ struct sockaddr_in *sin_addr = (void *)ai->ai_addr;
+
+ canon_host = xstrdup(ai->ai_canonname);
+ inet_ntop(AF_INET, &sin_addr->sin_addr,
+ addrbuf, sizeof(addrbuf));
+ ipaddr = addrbuf;
+ break;
+ }
+ freeaddrinfo(ai0);
+ }
+ }
+#else
+ {
+ struct hostent *hent;
+ struct sockaddr_in sa;
+ char **ap;
+ static char addrbuf[HOST_NAME_MAX + 1];
+
+ hent = gethostbyname(interp_table[INTERP_SLOT_HOST].value);
+ canon_host = xstrdup(hent->h_name);
+
+ ap = hent->h_addr_list;
+ memset(&sa, 0, sizeof sa);
+ sa.sin_family = hent->h_addrtype;
+ sa.sin_port = htons(0);
+ memcpy(&sa.sin_addr, *ap, hent->h_length);
+
+ inet_ntop(hent->h_addrtype, &sa.sin_addr,
+ addrbuf, sizeof(addrbuf));
+ ipaddr = addrbuf;
+ }
+#endif
+
+ interp_table[INTERP_SLOT_CANON_HOST].value = canon_host; /* FIXME: Leak */
+ interp_table[INTERP_SLOT_IP].value = xstrdup(ipaddr); /* FIXME: Leak */
+}
+
+
static int execute(struct sockaddr *addr)
{
static char line[1000];
@@ -451,8 +534,10 @@ #endif
if (len && line[len-1] == '\n')
line[--len] = 0;
- if (len != pktlen)
+ if (len != pktlen) {
parse_extra_args(line + len + 1, pktlen - len - 1);
+ fill_in_extra_table_entries(interp_table);
+ }
for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
struct daemon_service *s = &(daemon_service[i]);
@@ -656,12 +741,11 @@ static int set_reuse_addr(int sockfd)
#ifndef NO_IPV6
-static int socksetup(int port, int **socklist_p)
+static int socksetup(char *host, int port, int **socklist_p)
{
int socknum = 0, *socklist = NULL;
int maxfd = -1;
char pbuf[NI_MAXSERV];
-
struct addrinfo hints, *ai0, *ai;
int gai;
@@ -672,7 +756,7 @@ static int socksetup(int port, int **soc
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
- gai = getaddrinfo(NULL, pbuf, &hints, &ai0);
+ gai = getaddrinfo(host, pbuf, &hints, &ai0);
if (gai)
die("getaddrinfo() failed: %s\n", gai_strerror(gai));
@@ -726,20 +810,27 @@ #endif
#else /* NO_IPV6 */
-static int socksetup(int port, int **socklist_p)
+static int socksetup(char *host, int port, int **socklist_p)
{
struct sockaddr_in sin;
int sockfd;
- sockfd = socket(AF_INET, SOCK_STREAM, 0);
- if (sockfd < 0)
- return 0;
-
memset(&sin, 0, sizeof sin);
sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_port = htons(port);
+ if (host) {
+ /* Well, host better be an IP address here. */
+ if (inet_pton(AF_INET, host, &sin.sin_addr.s_addr) <= 0)
+ return 0;
+ } else {
+ sin.sin_addr.s_addr = htonl(INADDR_ANY);
+ }
+
+ sockfd = socket(AF_INET, SOCK_STREAM, 0);
+ if (sockfd < 0)
+ return 0;
+
if (set_reuse_addr(sockfd)) {
close(sockfd);
return 0;
@@ -848,13 +939,14 @@ static void store_pid(const char *path)
fclose(f);
}
-static int serve(int port, struct passwd *pass, gid_t gid)
+static int serve(char *host, int port, struct passwd *pass, gid_t gid)
{
int socknum, *socklist;
- socknum = socksetup(port, &socklist);
+ socknum = socksetup(host, port, &socklist);
if (socknum == 0)
- die("unable to allocate any listen sockets on port %u", port);
+ die("unable to allocate any listen sockets on host %s port %u",
+ host, port);
if (pass && gid &&
(initgroups(pass->pw_name, gid) || setgid (gid) ||
@@ -866,7 +958,8 @@ static int serve(int port, struct passwd
int main(int argc, char **argv)
{
- int port = DEFAULT_GIT_PORT;
+ int port = 0;
+ char *host = NULL;
int inetd_mode = 0;
const char *pid_file = NULL, *user_name = NULL, *group_name = NULL;
int detach = 0;
@@ -883,6 +976,14 @@ int main(int argc, char **argv)
for (i = 1; i < argc; i++) {
char *arg = argv[i];
+ if (!strncmp(arg, "--host=", 7)) {
+ char *p = arg + 7;
+ char *ph = host = xmalloc(strlen(arg + 7) + 1);
+ while (*p)
+ *ph++ = tolower(*p++);
+ *ph = 0;
+ continue;
+ }
if (!strncmp(arg, "--port=", 7)) {
char *end;
unsigned long n;
@@ -988,6 +1089,11 @@ int main(int argc, char **argv)
if (inetd_mode && (group_name || user_name))
die("--user and --group are incompatible with --inetd");
+ if (inetd_mode && (port || host))
+ die("--host= and --port= are incompatible with --inetd");
+ else if (port == 0)
+ port = DEFAULT_GIT_PORT;
+
if (group_name && !user_name)
die("--group supplied without --user");
@@ -1036,5 +1142,5 @@ int main(int argc, char **argv)
if (pid_file)
store_pid(pid_file);
- return serve(port, pass, gid);
+ return serve(host, port, pass, gid);
}
--
1.4.2.1.g85d8-dirty
^ permalink raw reply related
* Re: [PATCH] Cleaned up git-daemon virtual hosting support.
From: Jon Loeliger @ 2006-09-26 13:37 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vd59jw9lb.fsf@assigned-by-dhcp.cox.net>
So, like, the other day Junio C Hamano mumbled:
> > Added --host=host_or_ipaddr option suport.
>
> I wonder if --listen= might be more appropriate name:
Hmmm... I had asked it you wanted to incorporate a ":<port>"
notion into the listen address. Turns out that is a bad idea
since the <host_or_ipaddr> part can also be a IPv6 address
just riddled with colon characters.
I'll just leave it "--listen=<host_or_ipaddr>" and "--port=<n>".
jdl
^ permalink raw reply
* Re: [PATCH] Cleaned up git-daemon virtual hosting support.
From: Jon Loeliger @ 2006-09-26 13:12 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vd59jw9lb.fsf@assigned-by-dhcp.cox.net>
So, like, the other day Junio C Hamano mumbled:
> > Added --host=host_or_ipaddr option suport.
>
> I wonder if --listen= might be more appropriate name:
> "Listen a.b.c.d:port" (Apache),
No problem. I'll respin that to use
--listen=<ip_or_host>
Do you want this?:
--listen=[<ip_or_host>][:<port>]
And if you do, does --port= just go away, fade away, or remain?
Would you prefer patch-on-patch or respin?
jdl
^ permalink raw reply
* Re: [RFC/PATCH] gitweb: Add committags support
From: Jakub Narebski @ 2006-09-26 11:52 UTC (permalink / raw)
To: git
In-Reply-To: <20060925201500.GG20017@pasky.or.cz>
Petr Baudis wrote:
> Dear diary, on Mon, Sep 25, 2006 at 08:06:44PM CEST, I got a letter
> where Jakub Narebski <jnareb@gmail.com> said that...
>> So when putting message if into commit message, just put the commit
>> message in separate line, perhaps even with some indentation, like
>> below:
>> Msg-Id: <200609231533.02455.jnareb@gmail.com>
>
> Oh please. :-) The tool should bend, not the user.
Still it is more (much more) readable to have Msg-Id "header" (or
equivalent), and message id itself in one line.
> Are you going to mandate that for bug references as well? Or should I
> proofread all of my commits (if they aren't actually just autoformatted
> by fmt without my further review) to verify that they don't actually end
> up wrapped, and manually reformat the whole paragraph?
O.K. that convinces me (although wrapped hyperlink is not a pretty thing).
Besides for tags we have natural multiline "tag", namely PGP signature,
which we wpuld (most probably) want to syntax highlight wrapping it in
<div class="GPG_signature">...</div> element.
--
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
^ permalink raw reply
* [PATCH] git-svn: Fix fetch --no-ignore-externals with GIT_SVN_NO_LIB=1
From: Sergey Vlasov @ 2006-09-26 9:42 UTC (permalink / raw)
To: Eric Wong; +Cc: git, Sergey Vlasov
When using Subversion 1.3.1 without Perl bindings (GIT_SVN_NO_LIB=1),
"git-svn fetch --no-ignore-externals" fails with errors like:
Tree (.../.git/svn/git-svn/tree) is not clean:
X directory_with_external
In this case the 'X' lines in the "svn status" output are not a sign
of unclean tree, and therefore should be ignored.
Signed-off-by: Sergey Vlasov <vsu@altlinux.ru>
---
git-svn.perl | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/git-svn.perl b/git-svn.perl
index 0290850..2f5cf90 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -1246,6 +1246,7 @@ sub assert_svn_wc_clean {
}
my @status = grep(!/^Performing status on external/,(`svn status`));
@status = grep(!/^\s*$/,@status);
+ @status = grep(!/^X/,@status) if $_no_ignore_ext;
if (scalar @status) {
print STDERR "Tree ($SVN_WC) is not clean:\n";
print STDERR $_ foreach @status;
--
1.4.2.1.ga8608c
^ permalink raw reply related
* Re: [PATCH] gitweb: tree view: eliminate redundant "blob"
From: Jakub Narebski @ 2006-09-26 9:22 UTC (permalink / raw)
To: git
In-Reply-To: <efapsl$e65$1@sea.gmane.org>
Jakub Narebski wrote:
> Nak.
Gaaah. I can see that it is applied in next. I'd rather it would not.
Redundancy is sometimes good.
--
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
^ permalink raw reply
* Re: [PATCH] gitweb: "raw" links to blobs at HEAD
From: Jakub Narebski @ 2006-09-26 8:58 UTC (permalink / raw)
To: git
In-Reply-To: <20060926053920.47709.qmail@web31802.mail.mud.yahoo.com>
Luben Tuikov wrote:
> Currently there is no HTML interface which references (or
> can be externally referenced) to yield a _binary_ blob at
> HEAD. There is one for non-binary blobs, but none for
> binary ones.
You can in the same number of steps. First go to _tree_
at head, then click on "raw" link.
It's true that decision that binary files are automatically
redirected to "plain" ("raw") format, so they don't have "html"
output caused that there is no link for binary blob at head.
But I don't think that changing "raw" link to link to HEAD
version, while all other links are to current version is
a good idea...
--
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
^ permalink raw reply
* Re: [PATCH] gitweb: tree view: eliminate redundant "blob"
From: Jakub Narebski @ 2006-09-26 8:54 UTC (permalink / raw)
To: git
In-Reply-To: <20060926053816.54951.qmail@web31815.mail.mud.yahoo.com>
Luben Tuikov wrote:
> Binary and non-binary blobs:
>
> The "list" table element of tree view is identical
> to the "blob" link part of the link table element.
> I.e. clicking on "blob" is identical to clicking on
> the entry itself.
>
> Thus, eliminate "blob" from being shown -- the user
> can get identical result by simply clicking on the
> entry itself.
I'd rather not. The fact that the file name and tree name is link,
and the fact that commit title and tag title is link is a _convenience_.
Not always it is visible (without mouseover) that it is link.
And it is _not_ visible in the case of files!
And for example for commits and heads there are two possible
views, commit and commitdiff for commit, shortlog and log for head,
of which we arbitrary chose one for the subject link. So in that
case the additional self link is needed. I'd rather have both.
And for consistency I'd rather always have visible form default
self link/
I'd rather have additional link, than cause confusion to the users.
Perhaps we could separate the self link ("blob" for files, "tree"
for directories) into separate column?
Besides, you have to mouse over the name of file, or name of
directory to see to what view it would lead on.
Nak.
--
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
^ permalink raw reply
* Re: [PATCH] perl bindings fix compilation errors
From: Johannes Schindelin @ 2006-09-26 8:34 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Andy Whitcroft, git
In-Reply-To: <7vfyeftehf.fsf@assigned-by-dhcp.cox.net>
Hi,
On Mon, 25 Sep 2006, Junio C Hamano wrote:
> It is certainly incorrect to say that it is a driver error to
> git-pull (or git-checkout to switch branches) without running
> "make clean" first to get rid of perl/Git.c while your Makefile
> still knows it is a generated file. Our Makefile should be more
> helpful.
How about this:
diff --git a/Makefile b/Makefile
index d3310ae..a722c5a 100644
--- a/Makefile
+++ b/Makefile
@@ -612,7 +612,14 @@ ### Build rules
all: $(ALL_PROGRAMS) $(BUILT_INS) git$X gitk gitweb/gitweb.cgi \
git-merge-recur$X
-all: perl/Makefile
+# work around for left-over files
+.PHONY: perl/check-left-over
+
+perl/check-left-over:
+ (test -f perl/Git.c && test ! -f perl/Git.xs \
+ && rm perl/{Git.c,Git.bs,Makefile}) || true
+
+all: perl/check-left-over perl/Makefile
$(MAKE) -C perl
$(MAKE) -C templates
^ permalink raw reply related
* Re: [PATCH 3/5] gitweb: Split validate_input into validate_pathname and validate_refname
From: Jakub Narebski @ 2006-09-26 7:55 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7v1wpzw9l9.fsf@assigned-by-dhcp.cox.net>
Dnia wtorek 26. września 2006 06:11, Junio C Hamano napisał:
> Jakub Narebski <jnareb@gmail.com> writes:
>
> > @@ -387,16 +400,37 @@ sub href(%) {
> > ##
======================================================================
> > ## validation, quoting/unquoting and escaping
> >
> > -sub validate_input {
> > - my $input = shift;
> > +sub validate_pathname {
> > + my $input = shift || return undef;
> >
> > - if ($input =~ m/^[0-9a-fA-F]{40}$/) {
> > - return $input;
> > + # no '.' or '..' as elements of path, i.e. no '.' nor '..'
> > + # at the beginning, at the end, and between slashes.
> > + if ($input =~ m!(^|/)(|\.|\.\.)(/|$)!) {
> > + return undef;
> > }
> > - if ($input =~ m/(^|\/)(|\.|\.\.)($|\/)/) {
> > + # no doubled slashes
> > + if ($input =~ m!//!) {
> > return undef;
> > }
>
> I do not think you need the second check for double-slash. The
> pattern you borrowed from the original:
>
> /(^|\/)(|\.|\.\.)($|\/)/)
>
> cleverly matches an empty string with $2, so you already match
> double-slash with $1 = '/' $2 = '' $3 = '/', don't you?
Do I need to resend patch, then, to remove this unnecessary check?
> > + # it must be correct pathname
> > + $input = validate_pathname($input)
> > + or return undef;
> > + # restrictions on ref name according to git-check-ref-format
> > + if ($input =~ m!(/\.|\.\.|[\000-\040\177 ~^:?*\[]|/$)!) {
> > return undef;
> > }
>
> Why would you need validate_pathname here?
refname _must_ be a valid pathname, no? It means for example that it
cannot have double slashes, not NUL (the only thinkg not covered by
git-check-ref-format restrictions). Well, we could add that to regexp
instead...
--
Jakub Narebski
Poland
^ permalink raw reply
* Re: [PATCH] svnimport add support for parsing From lines for author
From: Andy Whitcroft @ 2006-09-26 7:51 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7v7izrtdtw.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano wrote:
> Andy Whitcroft <apw@shadowen.org> writes:
>
>> svnimport: add support for parsing From: lines for author
>
> Please do _not_ repeat the summary line in the message body. It
> is on the Subject: already.
Sorry ... different projects different rules.
>> Now that we have support for parsing Signed-off-by: for author
>> information it makes sense to handle From: as well.
>
> I take that you are referring to Sasha's change in ae35b304; I
> asked for actual svn users for ACK/NACK but I did not hear any.
> Can I understand that you use svnimport for real projects and
> are happy with Sasha's change? --- that would be an ack that
> would help me sleep better ;-).
Heh. Yeah I am tracking a small SVN repository which is using the
kernel DCO. we have From:/S-o-b: much as akpm uses in -mm. This was
the result of seeing that change and wanting to see if it would pick up
our sign-offs. It only seemed deficient in From: handling :). It seems
to work well in practice for me.
>
>> adds a new -F which will handle From: lines in the comments. It
>> may be used in combination with -S.
>
> This sort of makes sense but how common is this?
I think the kernel DCO has started a trend which will expand to other
projects. The problem it is intended to fix is a general one which
needs addressing in all such projects.
> I also wonder instead of piling up custom flags if it is better
> to let match-and-extract pattern be specified from the command
> line.
I did look at reusing the -S flag, such that -S would be S-o-b: handling
and -SS would be S-o-b: and From:, but this script is currently using
the old getopt implementation which doesn't record repeats.
So you're proposing something more like:
git svn-import -S "Signed-off-by:" -S "From:" ...
Again, we'll have to update the options handling to get that kind of
behaviour. How would you feel about -SS in this context.
-apw
^ permalink raw reply
* Re: [PATCH 5/5] gitweb: Quote filename in HTTP Content-Disposition: header
From: Jakub Narebski @ 2006-09-26 7:51 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7v7izrw9la.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano wrote:
> Jakub Narebski <jnareb@gmail.com> writes:
>
>> Finish work started by a2f3db2f5de2a3667b0e038aa65e3e097e642e7d commit
>> (although not documented in commit message) of quoting using quotemeta
>> the filename in HTTP -content_disposition header. Uniquify output.
>>
>> Just in case filename contains end of line character.
>
> What do you mean by "uniquify output"?
It means alsways use 'inline; filename="' . (quotemeta <whatever>) . '"',
and not sometimes qq(...), sometimes "...\"...\"", and sometimes '...'.
--
Jakub Narebski
Poland
^ 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