One thing you might want to consider is variable types and
default values (eh, that makes two).When Linus first introduced the config mechanism, he made it so
that a loosely coupled set of programs can take the "Why should
I care about other programs configuration" attitude, and
actively encouraged to do so by allowing custom config parsers
inherit from the default parser, like the way git_diff_config()
falls back on git_default_config() when it does not recognize
the variable.It is quite a good design for most uses, except that it made it
inconvenient to implement things like "git-repo-config -l" and
"git-var -l". The point of this design _is_ that they cannot
know what the set of possible variables, their types and the
default values when missing are, so by design the script that
used "git-var -l | grep" to read the configuration needed to
know that a boolean can be denoted by existence, value set to
zero or non-zero integer, or string "true"/"false" (i.e.
"filemode", "filemode=1", and "filemode = true" mean the same
thing; BTW I think we would probably want to add "yes"/"no"
here).Later it was made easier to use by Pasky with "repo-config --type"
option. The caller supplies the name of the variable and the
type and repo-config gets the value -- the caller knows what it
wants to use, so having it to know what type of things it is
interested in is not so bad, so the type problem was practically
solved. But it still feels somewhat hacky.With (2) and (5), we have a bound set of "se.ct.ion.variable";
we could enumerate the variables we care about, define what they
mean and what their types and default values are (we need to do
that for Documentation/config.txt anyway). With many parts of
the standalone git plumbing programs migrating into builtins, I
think it is not a bad idea to have a central table of all the
configuration variables that the core knows about. Porcelains
and scripts could define customized tables that describe the
sections/variables they also ...
Here's my suggestion as a patch.
NOTE! This patch could be applied right now, and to all the branches (to
make 1.x, 1.2.x and 1.3.x all support the _syntax_). Even if nothing
actually uses it.It just makes the syntax be
[section<space>+"<randomstring>"]
where the only rule for "randomstring" is that it can't contain a newline,
and if you really want to insert a double-quote, you do it with \".It turns that into the section name "secion.randomstring".
So you could use this for things like
[email "torvalds@osdl.org"]
name = Linus Torvaldsif you wanted to do the "email->name" conversion as part of the config
file format (I'm not claiming that is sensible, I'm just giving it as an
insane example). That would show up as the associationemail.torvalds@osdl.org.name -> Linus Torvalds
which is easy to parse (the "." in the email _looks_ ambiguous, but it
isn't: you know that there will always be a single key-name, so you find
the key name with "strrchr(name, '.')" and things are entirely
unambiguous).Now, it doesn't do any repo-config stuff, since the whole point of this is
to make this a legal syntax, not actually start _using_ it yet. If people
think this is an acceptable syntax, then pls apply to everything, and
worry about usage later.Linus
---
diff --git a/config.c b/config.c
index 0f518c9..f3b74e0 100644
--- a/config.c
+++ b/config.c
@@ -134,6 +134,41 @@ static int get_value(config_fn_t fn, cha
return fn(name, value);
}+static int get_extended_base_var(char *name, int baselen, int c)
+{
+ do {
+ if (c == '\n')
+ return -1;
+ c = get_next_char();
+ } while (isspace(c));
+
+ /* We require the format to be '[base "extension"]' */
+ if (c != '"')
+ return -1;
+ name[baselen++] = '.';
+
+ for (;;) {
+ int c = get_next_char();
+ if (c == '\n')
+ return -1;
+ if (c == '"')
+ break;
+ if (c == '\\') {
+ c = get_next_char();
+ if (c == '\n')
+ return -1;
+ }
+ name[bas...
Linus,
I've adjusted this patch, your follow-up patch, and Sean's
"extended section part is case sensitive" patch, along with the
test tweak to "maint" branch. I also prepared them to be
mergeable to the "master" branch. Tentatively it is in "next"
for testing.I'm ready to push out "maint" (not tagged as 1.3.3 yet) and
"next", but have not done so.I understand the plan is to have 1.3.3 out from this "maint",
and also merge this in "master" about the same time, but I am
expecting I will be offline for the rest of the week most of the
time, so it would happen over the weekend at the earliest.Does that sound good to you?
I do not think we would need v1.1.7 nor v1.2.7 for this. People
who have stayed at v1.1.6 or v1.2.6 would need to update if they
are going to use newer git in their repo anyway, and I do not
think of a reason not to update to 1.3.3 but update to 1.1.7 or
1.2.7 in order to stay at the feature level of 1.1.X or 1.2.X
series. We haven't made incompatible changes as far as I
remember.Here is what the (adjusted) test case in "next" looks like.
Corresponding one in "maint" lack --list so does not have the
last hunk. The "maint" and "next" branches I have locally both
passes the test.-- >8 --
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index 7090ea9..8260d57 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -229,7 +229,7 @@ test_expect_failure 'invalid key' 'git-r
test_expect_success 'correct key' 'git-repo-config 123456.a123 987'test_expect_success 'hierarchical section' \
- 'git-repo-config 1.2.3.alpha beta'
+ 'git-repo-config Version.1.2.3eX.Alpha beta'cat > expect << EOF
[beta] ; silly comment # another comment
@@ -241,8 +241,8 @@ # empty line
NoNewLine = wow2 for me
[123456]
a123 = 987
-[1.2.3]
- alpha = beta
+[Version "1.2.3eX"]
+ Alpha = beta
EOFtest_expect_success 'hierarchical section value' 'cmp .git/config expect'
@@ -251,7 +251,7 @@ cat > expect <...
On Tue, 9 May 2006 12:24:02 -0700 (PDT)
Lightly tested here. Looks good.
Sean
-
On Tue, 9 May 2006 15:44:59 -0400
Linus,
I really tried to like your patch ;o) But it breaks the repo-config command
line and causes mixing of some branches using old style [branch.xyz] and new
style [branch "XYZ"] which just doesn't seem to be the right thing to do.The following patch produced for sake of discussion just allows section
headers to contain whatever characters are needed to get the job done.git-repo-config works properly with no further need of change. Section
headers become case sensitive but key identifiers within sections do not.
AFAIK there should be no backward compatibility issues with regard to
case sensitivity. All tests pass after having been fixed up to remove
the assumption that section names are case insensitive.The syntax is:
[<random string>]
Here's how your example would look in this style:
[email.torvalds@osdl.org]
name = Linus TorvaldsAnd there's no strange syntax needed with repo-config to set and get it:
$ git repo-config email.torvalds@osdl.org.name
Linus Torvaldsand just to show that key names are still case insensitive:
$ git repo-config email.torvalds@osdl.org.NAME
Linus TorvaldsSetting new sections is unambiguous from the command line and
doesn't have to decide whether to use the [branch "<string>"] or
[branch.section.name] format.$ git repo-config branch.branch.x y
$ git repo-config branch.WonkKY.x y
$ git repo-config --get-regexp branch.\*
branch.branch.x y
branch.WonkKY.x y[email.torvalds@osdl.org]
name = Linus Torvalds
[branch.branch]
x = y
[branch.WonkKY]
x = ySean
---config.c | 11 +++++++----
repo-config.c | 8 ++++----
t/t1300-repo-config.sh | 38 ++++++++++++++++++++++----------------
3 files changed, 33 insertions(+), 24 deletions(-)diff --git a/config.c b/config.c
index 0f518c9..5d19ae9 100644
--- a/config.c
+++ b/config.c
@@ -144,11 +144,14 @@ static int get_base_var...
Well, obviously it's _simpler_ to have the machine-readable format as-is,
and say "don't try to make it human-readable". But the repo-config patch
to make it human-readable isn't that hard.And it's _not_ that hard to make repo-config do the right thing.
Here's a pretty lightly tested patch (on top of my previous one) that does
exactly that.(The first part just fixes an indentation bug)
Linus
---
diff --git a/config.c b/config.c
index f3b74e0..12c51b1 100644
--- a/config.c
+++ b/config.c
@@ -372,10 +372,12 @@ static int store_aux(const char* key, co
store.offset[store.seen] = ftell(config_file);
store.state = KEY_SEEN;
store.seen++;
- } else if (strrchr(key, '.') - key == store.baselen &&
+ } else {
+ if (strrchr(key, '.') - key == store.baselen &&
!strncmp(key, store.key, store.baselen)) {
store.state = SECTION_SEEN;
store.offset[store.seen] = ftell(config_file);
+ }
}
}
return 0;
@@ -383,8 +385,30 @@ static int store_aux(const char* key, costatic void store_write_section(int fd, const char* key)
{
+ const char *dot = strchr(key, '.');
+ int len1 = store.baselen, len2 = -1;
+
+ dot = strchr(key, '.');
+ if (dot) {
+ int dotlen = dot - key;
+ if (dotlen < len1) {
+ len2 = len1 - dotlen - 1;
+ len1 = dotlen;
+ }
+ }
+
write(fd, "[", 1);
- write(fd, key, store.baselen);
+ write(fd, key, len1);
+ if (len2 >= 0) {
+ write(fd, " \"", 2);
+ while (--len2 >= 0) {
+ unsigned char c = *++dot;
+ if (c == '"')
+ write(fd, "\\", 1);
+ write(fd, &c, 1);
+ }
+ write(fd, "\"", 1);
+ }
write(fd, "]\n", 2);
}@@ -458,7 +482,7 @@ int git_config_set(const char* key, cons
int git_config_set_multivar(const char* key, const char* value,
const char* value_regex, int multi_replace)
{
- int i;
+ int i, dot;
int fd = -1, in_fd;
int ret;
char* config_filename = strdup(git_path("config"));
@@ -483,16 +507,23 @@ int git_config_set_multi...
On Tue, 9 May 2006 17:17:58 -0700 (PDT)
So every mutli-part section is going to be of the form:
[section "big long opaque string"]
It seems to handle everything, you have me convinced.
Sean
-
That's what my stupid patch does now. It seems to work well for all cases,
but if we were to care, we could have some special heuristics for
different section names (ie "if subsection is all lower-case
alphanumerics, and the section name is one of the following, use the
old-fashioned format").I don't see _why_ we'd ever do that, but we certainly _could_, if it were
to make more sense that way for some section name.However, if you already use a syntax like
[section.subsection]
key = 1and then do
git-repo-config --replace-all section.subsection.new 2
it will actually keep the old section header, so you'll end up with
[section.subsection]
key = 1
new = 2but if you create a _new_ subsection (and since subsections are now case
sensitive, this example is a "new" subsection):git-repo-config --replace-all section.SubSection.new 3
you will now have
[section.subsection]
key = 1
new = 2
[section "SubSection"]
new = 3(ie notice how it did _not_ replace the old "section.subsection.new",
because of how this is a _different_ subsection due to the subsectin
rules, and notice how it will always create the new subsection with
quotes).So you _can_ continue to use the old subsection format, and it will work
the way it always did, except for the fact that it would now be deprecated
(if there were any multi-level users, which I don't think there are), and
it is now case-sensitive (which makes sense in the new format with ""Hey, it was fun, and the only ugly part was the write-out of the quoted
format.And it should be perfectly easy to use. Modulo double-quotes in branch
names, you can do trivial things likegit repo-config "branch.$branchname.remote" "git://git.kernel.org/..."
and it will do the obvious thing.
My one complaint is that I think we should add an empty line for the case
where we add a new sub-section to the end of a file. That's not a new
problem, but that was really the only visually ugly part I...
Good one. I'm following this thread with interest, but it feels we've
been attacked by the 'bike shed bug' in the act of redesigning
Windows.ini.As an end-user, I have personally stayed away from the increasingly
complex scheme for remotes waiting for it to settle, and stuck with
the old-styled .git/branches stuff which is slam-dunk simple and it
just works.The normal non-branch config options don't need any of this fancy
stuff. And I think the branches is reasonably well managed as files as
is done in .git/remotes which is trivial to work on with standard
shell commands. What I mean is that I can grep them trivially to ask
"how many remotes pull from server X" or from repo Y. Or via rsync.Also -- repo config is tricky in the sense of scope. I want all my
"dev" repos of different projects on my laptop to have mostly the same
config but radically different remotes listings.So... call me old-styled... but I'm happy with one-file-per-remote.
Was it broken to start with? Should we restart the track renames
flameway instead?cheers,
martin
-
Sure. It clearly _is_ a bike shed, which is why I posted patches: I think
the way to resolve bike sheds is to "just do it". In the kernel, the
general rule ends up being "he who writes the code gets to choose how it
gets done", because it turns out that there are a lot more people willing
to _argue_ about code than there are people willing to _write_ it, and
thus that "real code wins" rule actually works very well in practice.I don't think I've ever really seen an argument where you ended up having
seriously competing patches. Yes, you can have patches to do things
different ways, but once you have that, it tends to be pretty easy for the
maintainer to just draw a line in the sand. And once one patch has been
accepted, it's all over.So the real problem with "bike sheds" is actually when you have a culture
of arguing, and not enough of a culture of "just do it".If you have a "just do it" culture, bike sheds are often good things. If
it really _is_ that easy, a bike shed is a perfect opportunity for
somebody who isn't all that deeply into a project to make a contribution
and start feeling more comfy about it. It obviously didn't happen here,
but it's definitely true that a lot of people in the kernel get introduced
to doing patches through various "trivial" things.So don't knock the bike sheds. It's a BSD term, and I think there's a
_reason_ why it's a BSD term. Those people seem to sometimes like to argue
about theoretical things (or about anything else, for that matter) moreIt does work, and I think it's nice in many ways. It was certainly a good
way to prototype things.At the same time, especially with moving things more to C (or almost any
other language, for that matter - shell is really pretty special in making
it _easier_ to have things in individual files), it's in many ways nicer
to have a more structured representation that has a nice fixed interface
and a library and known access methods behind it.And I'm personally actually p...
Apologies -- I didn't want to know it, but I do wonder what the gain
behind the change is. It seems to me that it would be a bad idea to
store refs in the config file and, in my mind at least, branch info isBut it is a bit of a loss for perl/shell porcelains, and for users
that abuse the contents of .git directly on a regular basis...there's nothing to stop us from having a structured representation of
Agreed, it's a mess, but I suspect it's still there to support cogito.
In keeping with the 'talk code' ethos, I'll work on adding support forWhat about one semantics, one file? So far we have had 3 semantics:
git config, remotes, refs. And git config has been mostly
project-indepentent. In fact, I have been copying it across my
checkouts of different, unrelated projects. You just don't do that
with remotes or refs.cheers,
martin
-
I think we can do better in a few pretty important regards:
- having the information in one place. I agree that the multi-file
approach works fine for shell scripts (although I disagree that the new
one would be harder - you just use git-repo-config instead), but I
think it's quite confusing from a new user perspective.I bet that even without any tools, new users can be told to just open
".git/config", and guess how hard a time they would have to add a new
branch, if they already had one that said[branch "origin"]
remote = git://git.kernel.org/pub/scm/git/git.git
branch masterwhich would tell you that the local branch "origin" is really branch
"master" at that remote git repository.Yeah, I'm not sure what the actual config rules would be, but think it
would be a hell of a lot more intuitive than what we have now.What we have now _works_. It works really well. No question about that.
It's just pretty hard to explain. The above syntax wouldn't even need
any explanation. You could just tell people to look into their config
files.- I think we'll have a much easier time (from a purely technical angle)
to add special attributes to the local branches. Add a "read-only"
specifier? It's _obvious_:[branch "origin"]
remote = git://git.kernel.org/pub/scm/git/git.git
branch master
readonlyand it's absolutely trivial to parse. And part of the important thing
is that this all makes 100% sense EVEN IF IT'S NOT A REMOTE REPO!So imagine that it's a purely local branch, but you want to protect it.
Solution?[branch "July Snapshot"]
readonlyand you're done. In contrast, even if you ended up just extending the
file format for the .git/remotes/July\ Snapshot file, and just added a
"readonly" line to it, it wouldn't make _sense_. Whaa? "remotes"? In
contrast, in the .git/config file, it makes a ton of sense, and in fact
it's totally obvious.(Act...
I totally agree with the principle, but I find the above really
confusing. Which "branch" means what? At least if it was "remote_url"
and "remote_branch" then there wouldn't be any possibility for
confusion.Nicolas
-
As you say, this needs to be explained/exposed better to the user.
Now, how about having one .git/config and one .git/branches file?Agreed, but I suspect repo config and branches config travel at
different speeds. Maybe what this means is that if this happens, we'll
start seeing a need for ~/.git/config and /etc/git/config to set
defaults (merge.summary=1 for all my repos, core.sharedrepository=1
for all the repos on this server) where I now I just mostly copy
.git/config around.Must be me... it's not the Perl part... I just do a lot of grep |
xargs | sed stuff in my daily git usage ;-)cheers,
martin
-
Hi,
Why not just edit the template?
Ciao,
Dscho-
Btw, I seriously believe that git has come to the point where we've licked
the real technical issues. Stability hasn't been a concern for the last
year - and even something as seriously as a repacking bug causing a
SIGSEGV (yesterday) was actually basically designed to not be able to
cause problems. The repack failed, and nothing happened to the old data.
It was scary, but it wasn't "bad".The last performance problem was a stupid one-liner, where one of the
shell scripts didn't use the "--aggressive" flag for doing the trivial
three-way merge, so it ended up forking and executing the "merge-one-file"
shell script for 4500+ files for one unfortunate project that had a
strange workflow. Adding the "--aggressive" flag took a 5-minute (where
all of the time was spent in a shell script basically doing nothing) thing
down to under a second.So git should kick butt in performance, scale very well, and seems to take
less disk space than just about anybody else.So what do people actually _complain_ about?
I don't think we've seen a serious complaint lately that hasn't been about
nice user interface and/or documentation. Anybody?So as far as I can tell, the #1 issue is that "new user" experience. You
can pretty much forget about anything else. Working with git in a
distributed manner is really easy and efficient, but from the comments
I've seen, it's not always easy and obvious how to get to that point.Creating a remote repository and filling it. And being able to understand
what the local vs remote branches actually _mean_. And I think our current
.git/remotes/ thing is a part of that. It's not exactly user _hostile_,
but it's very much "implementation friendly, and doesn't care about the
user". So I think .git/config can help us there.I also think we could do with a few scripts to just do setup of a remote
repo:git remote clone <remoteaddress>
git remote branch <remoteaddress> [-D]
git remote fsck <remoteaddress>
gi...
Here's a 'git remote' that handles the easy commands. It makes things
like 'git remote origin repack -a -d' do what you expect. The biggest
problems are:
- it only works for ssh remotes
- it assumes your remote path is a git dir (do we have a usual way of
deciding between $path and $path/.git?)
- ssh'ing will mangle your shell quoting in the command arguments
- the url parsing is somewhat ad-hoc (do we have a usual way of
parsing urls for shell scripts?)---
Add braindead git-remote script.This script is a convenience wrapper for performing remote commands on a
repository using ssh.---
Makefile | 2 +-
git-remote.sh | 19 +++++++++++++++++++
2 files changed, 20 insertions(+), 1 deletions(-)
create mode 100644 git-remote.sh8810ae2524d3339b8a8341b34b2d3f14ddb9c899
diff --git a/Makefile b/Makefile
index 37fbe78..58eddd8 100644
--- a/Makefile
+++ b/Makefile
@@ -125,7 +125,7 @@ SCRIPT_SH = \
git-applymbox.sh git-applypatch.sh git-am.sh \
git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \
git-merge-resolve.sh git-merge-ours.sh git-grep.sh \
- git-lost-found.sh
+ git-lost-found.sh git-remote.shSCRIPT_PERL = \
git-archimport.perl git-cvsimport.perl git-relink.perl \
diff --git a/git-remote.sh b/git-remote.sh
new file mode 100644
index 0000000..04b1ce9
--- /dev/null
+++ b/git-remote.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+USAGE='<remote> <command> [options]'
+. git-sh-setup
+. git-parse-remote
+
+case "$#" in
+ 0|1) usage ;;
+esac
+
+remote=`get_remote_url "$1"` shift;
+case "$remote" in
+ ssh://*|git+ssh://*|ssh+git://*)
+ host=`echo "$remote" | sed 's!^[^/]*://\([^/]*\).*!\1!'`
+ path=`echo "$remote" | sed 's!^[^/]*://[^/]*\(.*\)!\1!'`
+ exec ssh -n $host "GIT_DIR=$path git $@"
+ ;;
+ *) die "unhandled protocol: $remote" ;;
+esac
--
1.3.1-
Oops, this should be:
remote=`get_remote_url "$1"`; shift
but it actually works fine under dash (a bug in dash?)-Peff
-
Hi,
Depends on how you look at it. A bunch of files is okay for quick-n-dirty,
where you do not care about locking or consistency or extensibility.Ciao,
Dscho-
On Tue, 9 May 2006 17:17:58 -0700 (PDT)
This patch or something like it is needed for repo-config in order to query
the new case sensitive portion of section names. This is on top of your two
patches:diff --git a/repo-config.c b/repo-config.c
index 63eda1b..9a9194f 100644
--- a/repo-config.c
+++ b/repo-config.c
@@ -65,11 +65,14 @@ static int show_config(const char* key_,
static int get_value(const char* key_, const char* regex_)
{
int i;
+ char *tl;
+
+ key = strdup(key_);
+ for (tl=key+strlen(key)-1; tl >= key && *tl != '.'; --tl)
+ *tl = tolower(*tl);
+ for (tl=key; *tl && *tl != '.'; ++tl)
+ *tl = tolower(*tl);- key = malloc(strlen(key_)+1);
- for (i = 0; key_[i]; i++)
- key[i] = tolower(key_[i]);
- key[i] = 0;if (use_key_regexp) {
key_regexp = (regex_t*)malloc(sizeof(regex_t));
-
How does a program (not a script, but git_config() users) get
that value and parse it?-
On Tue, 09 May 2006 15:42:25 -0700
Anything but LF; how's this for ugly:
The same way they do now. For instance git-repo-config processes
the config file using the same get_config() + callback as usual. The
only issue is that they should no longer cast everything to lower first.Sean
-
| Greg KH | [GIT PATCH] driver core patches against 2.6.24 |
| Justin C. Sherrill | Re: pkgsrc bulk build and tiff |
| Jeremy Allison | Re: [RFC] Heads up on sys_fallocate() |
| Roland Dreier | Re: Integration of SCST in the mainstream Linux kernel |
| Matt Thomas | Re: Add a MAP_ALIGNED flag for mmap(2). |
| Vsevolod Stakhov | Unicode support in iso9660. |
| Jaromir Dolecek | Re: Speeding up fork/wait path |
| matthew green | re: merge of freebsd eventhandler |
git: | |
| Petr Janda | KDE and OpenSSL = Broken |
| sam | Re: Loader not found |
| Erick Perez | Re: dragonfly pdf documentation |
| Michel Talon | Re: Compatability with FreeBSD Ports [debian package tools] |
