* [PATCH] parse-opt: migrate builtin-checkout-index.
From: Miklos Vajna @ 2008-10-19 18:30 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Pierre Habouzit, git
In-Reply-To: <1224292643-28704-1-git-send-email-vmiklos@frugalware.org>
Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>
---
On Sat, Oct 18, 2008 at 03:17:23AM +0200, Miklos Vajna <vmiklos@frugalware.org> wrote:
> > This adds a new feature to say --no-z from the command line, doesn't
> > it?
> > And I suspect the feature is broken ;-).
>
> Right, I fixed this in option_parse_z(). --no-z should set
> line_termination to \n instead of 1.
Originally in option_parse_z() I had
line_termination = unset;
which is in fact right, because (as Pierre pointed out) unset for short
options are always false, but I changed it to
line_termination = 0;
to make it more readable.
> > Is this comment still correct? Do the original and your version act
> > the
> > same way when the user says "checkout --stdin -f", for example? I
> > suspect
> > the original refused it and yours take it (and do much more sensible
> > thing), which would be an improvement, but then the error message
> > should
> > be reworded perhaps?
>
> Unless I missed something, that was a limitation of the option parser.
> checkout-index --stdin -f works fine for me after removing those two
> lines, so I left them out from the updated patch.
I still think that check is necessary, but the reasoning was false: what
we need to check is the usage of --stdin and filenames togother. But a
bit later there is a
die("git checkout-index: don't mix '--stdin' and explicit filenames");
so the check I removed was unnecessary.
Here is a patch with the cleaned up option_parse_z().
builtin-checkout-index.c | 149 +++++++++++++++++++++++++---------------------
1 files changed, 80 insertions(+), 69 deletions(-)
diff --git a/builtin-checkout-index.c b/builtin-checkout-index.c
index 4ba2702..2c558dd 100644
--- a/builtin-checkout-index.c
+++ b/builtin-checkout-index.c
@@ -40,6 +40,7 @@
#include "cache.h"
#include "quote.h"
#include "cache-tree.h"
+#include "parse-options.h"
#define CHECKOUT_ALL 4
static int line_termination = '\n';
@@ -153,11 +154,55 @@ static void checkout_all(const char *prefix, int prefix_length)
exit(128);
}
-static const char checkout_cache_usage[] =
-"git checkout-index [-u] [-q] [-a] [-f] [-n] [--stage=[123]|all] [--prefix=<string>] [--temp] [--] <file>...";
+static const char * const builtin_checkout_index_usage[] = {
+ "git checkout-index [options] [--] <file>...",
+ NULL
+};
static struct lock_file lock_file;
+static int option_parse_u(const struct option *opt,
+ const char *arg, int unset)
+{
+ int *newfd = opt->value;
+
+ state.refresh_cache = 1;
+ if (*newfd < 0)
+ *newfd = hold_locked_index(&lock_file, 1);
+ return 0;
+}
+
+static int option_parse_z(const struct option *opt,
+ const char *arg, int unset)
+{
+ line_termination = 0;
+ return 0;
+}
+
+static int option_parse_prefix(const struct option *opt,
+ const char *arg, int unset)
+{
+ state.base_dir = arg;
+ state.base_dir_len = strlen(arg);
+ return 0;
+}
+
+static int option_parse_stage(const struct option *opt,
+ const char *arg, int unset)
+{
+ if (!strcmp(arg, "all")) {
+ to_tempfile = 1;
+ checkout_stage = CHECKOUT_ALL;
+ } else {
+ int ch = arg[0];
+ if ('1' <= ch && ch <= '3')
+ checkout_stage = arg[0] - '0';
+ else
+ die("stage should be between 1 and 3 or all");
+ }
+ return 0;
+}
+
int cmd_checkout_index(int argc, const char **argv, const char *prefix)
{
int i;
@@ -165,6 +210,33 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
int all = 0;
int read_from_stdin = 0;
int prefix_length;
+ int force = 0, quiet = 0, not_new = 0;
+ struct option builtin_checkout_index_options[] = {
+ OPT_BOOLEAN('a', "all", &all,
+ "checks out all files in the index"),
+ OPT_BOOLEAN('f', "force", &force,
+ "forces overwrite of existing files"),
+ OPT__QUIET(&quiet),
+ OPT_BOOLEAN('n', "no-create", ¬_new,
+ "don't checkout new files"),
+ { OPTION_CALLBACK, 'u', "index", &newfd, NULL,
+ "update stat information in the index file",
+ PARSE_OPT_NOARG, option_parse_u },
+ { OPTION_CALLBACK, 'z', NULL, NULL, NULL,
+ "paths are separated with NUL character",
+ PARSE_OPT_NOARG, option_parse_z },
+ OPT_BOOLEAN(0, "stdin", &read_from_stdin,
+ "read list of paths from the standard input"),
+ OPT_BOOLEAN(0, "temp", &to_tempfile,
+ "write the content to temporary files"),
+ OPT_CALLBACK(0, "prefix", NULL, "string",
+ "when creating files, prepend <string>",
+ option_parse_prefix),
+ OPT_CALLBACK(0, "stage", NULL, NULL,
+ "copy out the files from named stage",
+ option_parse_stage),
+ OPT_END()
+ };
git_config(git_default_config, NULL);
state.base_dir = "";
@@ -174,72 +246,11 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
die("invalid cache");
}
- for (i = 1; i < argc; i++) {
- const char *arg = argv[i];
-
- if (!strcmp(arg, "--")) {
- i++;
- break;
- }
- if (!strcmp(arg, "-a") || !strcmp(arg, "--all")) {
- all = 1;
- continue;
- }
- if (!strcmp(arg, "-f") || !strcmp(arg, "--force")) {
- state.force = 1;
- continue;
- }
- if (!strcmp(arg, "-q") || !strcmp(arg, "--quiet")) {
- state.quiet = 1;
- continue;
- }
- if (!strcmp(arg, "-n") || !strcmp(arg, "--no-create")) {
- state.not_new = 1;
- continue;
- }
- if (!strcmp(arg, "-u") || !strcmp(arg, "--index")) {
- state.refresh_cache = 1;
- if (newfd < 0)
- newfd = hold_locked_index(&lock_file, 1);
- continue;
- }
- if (!strcmp(arg, "-z")) {
- line_termination = 0;
- continue;
- }
- if (!strcmp(arg, "--stdin")) {
- if (i != argc - 1)
- die("--stdin must be at the end");
- read_from_stdin = 1;
- i++; /* do not consider arg as a file name */
- break;
- }
- if (!strcmp(arg, "--temp")) {
- to_tempfile = 1;
- continue;
- }
- if (!prefixcmp(arg, "--prefix=")) {
- state.base_dir = arg+9;
- state.base_dir_len = strlen(state.base_dir);
- continue;
- }
- if (!prefixcmp(arg, "--stage=")) {
- if (!strcmp(arg + 8, "all")) {
- to_tempfile = 1;
- checkout_stage = CHECKOUT_ALL;
- } else {
- int ch = arg[8];
- if ('1' <= ch && ch <= '3')
- checkout_stage = arg[8] - '0';
- else
- die("stage should be between 1 and 3 or all");
- }
- continue;
- }
- if (arg[0] == '-')
- usage(checkout_cache_usage);
- break;
- }
+ argc = parse_options(argc, argv, builtin_checkout_index_options,
+ builtin_checkout_index_usage, 0);
+ state.force = force;
+ state.quiet = quiet;
+ state.not_new = not_new;
if (state.base_dir_len || to_tempfile) {
/* when --prefix is specified we do not
@@ -253,7 +264,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
}
/* Check out named files first */
- for ( ; i < argc; i++) {
+ for (i = 0; i < argc; i++) {
const char *arg = argv[i];
const char *p;
--
1.6.0.2
^ permalink raw reply related
* Re: [JGIT PATCH v2] Encode/decode index and tree entries using UTF-8
From: Robin Rosenberg @ 2008-10-19 18:24 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: git
In-Reply-To: <20081019171456.GC14786@spearce.org>
Decoding uses the same strategy as for commit messages and other string
entities. Encoding is always done in UTF-8. This is incompatible with
Git for non-unicode unices, but it leads to the expected behavior on
Windows and cross-locale sharing of repositories.
Signed-off-by: Robin Rosenberg <robin.rosnberg@dewire.com>
---
söndagen den 19 oktober 2008 19.14.56 skrev Shawn O. Pearce:
> Robin Rosenberg <robin.rosenberg.lists@dewire.com> wrote:
> > Decoding uses the same strategy as for commit messages and other string
> > entities. Encoding is always done in UTF-8. This is incompatible with
> > Git for non-unicode unices, but it leads to the expected behavior on
> > Windows and cross-locale sharing of repositories.
>
> FWIW I think this is a good idea.
Ok, so here's the update. We might want to move the encode out of Constants
too as it is no longer a utility for constants.
-- robin
.../src/org/spearce/jgit/lib/GitIndex.java | 27 ++++++++--------
.../src/org/spearce/jgit/lib/Tree.java | 16 ++++-----
.../src/org/spearce/jgit/lib/TreeEntry.java | 14 +++-----
.../src/org/spearce/jgit/util/RawParseUtils.java | 32 ++++++++++++++++++++
4 files changed, 58 insertions(+), 31 deletions(-)
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/GitIndex.java b/org.spearce.jgit/src/org/spearce/jgit/lib/GitIndex.java
index 22935ab..bafddef 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/GitIndex.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/GitIndex.java
@@ -63,6 +63,7 @@
import org.spearce.jgit.errors.CorruptObjectException;
import org.spearce.jgit.errors.NotSupportedException;
import org.spearce.jgit.util.FS;
+import org.spearce.jgit.util.RawParseUtils;
/**
* A representation of the Git index.
@@ -178,8 +179,9 @@ public Entry add(File wd, File f) throws IOException {
* @param f
* the file whose path shall be removed.
* @return true if such a path was found (and thus removed)
+ * @throws IOException
*/
- public boolean remove(File wd, File f) {
+ public boolean remove(File wd, File f) throws IOException {
byte[] key = makeKey(wd, f);
return entries.remove(key) != null;
}
@@ -300,11 +302,11 @@ static boolean File_hasExecute() {
return FS.INSTANCE.supportsExecute();
}
- static byte[] makeKey(File wd, File f) {
+ static byte[] makeKey(File wd, File f) throws IOException {
if (!f.getPath().startsWith(wd.getPath()))
throw new Error("Path is not in working dir");
String relName = Repository.stripWorkDir(wd, f);
- return relName.getBytes();
+ return Constants.encode(relName);
}
Boolean filemode;
@@ -376,7 +378,7 @@ Entry(TreeEntry f, int stage)
size = -1;
}
sha1 = f.getId();
- name = f.getFullName().getBytes("UTF-8");
+ name = Constants.encode(f.getFullName());
flags = (short) ((stage << 12) | name.length); // TODO: fix flags
}
@@ -580,7 +582,7 @@ private File getFile(File wd) {
}
public String toString() {
- return new String(name) + "/SHA-1(" + sha1.name() + ")/M:"
+ return getName() + "/SHA-1(" + sha1.name() + ")/M:"
+ new Date(ctime / 1000000L) + "/C:"
+ new Date(mtime / 1000000L) + "/d" + dev + "/i" + ino
+ "/m" + Integer.toString(mode, 8) + "/u" + uid + "/g"
@@ -591,7 +593,7 @@ public String toString() {
* @return path name for this entry
*/
public String getName() {
- return new String(name);
+ return RawParseUtils.decode(name);
}
/**
@@ -731,7 +733,7 @@ void readTree(String prefix, Tree t) throws IOException {
readTree(name, (Tree) te);
} else {
Entry e = new Entry(te, 0);
- entries.put(name.getBytes("UTF-8"), e);
+ entries.put(Constants.encode(name), e);
}
}
}
@@ -743,7 +745,7 @@ void readTree(String prefix, Tree t) throws IOException {
* @throws IOException
*/
public Entry addEntry(TreeEntry te) throws IOException {
- byte[] key = te.getFullName().getBytes("UTF-8");
+ byte[] key = Constants.encode(te.getFullName());
Entry e = new Entry(te, 0);
entries.put(key, e);
return e;
@@ -824,8 +826,7 @@ public ObjectId writeTree() throws IOException {
}
while (trees.size() < newName.length) {
if (!current.existsTree(newName[trees.size() - 1])) {
- current = new Tree(current, newName[trees.size() - 1]
- .getBytes());
+ current = new Tree(current, Constants.encode(newName[trees.size() - 1]));
current.getParent().addEntry(current);
trees.push(current);
} else {
@@ -835,7 +836,7 @@ public ObjectId writeTree() throws IOException {
}
}
FileTreeEntry ne = new FileTreeEntry(current, e.sha1,
- newName[newName.length - 1].getBytes(),
+ Constants.encode(newName[newName.length - 1]),
(e.mode & FileMode.EXECUTABLE_FILE.getBits()) == FileMode.EXECUTABLE_FILE.getBits());
current.addEntry(ne);
}
@@ -880,7 +881,7 @@ int longestCommonPath(String[] a, String[] b) {
* Small beware: Unaccounted for are unmerged entries. You may want
* to abort if members with stage != 0 are found if you are doing
* any updating operations. All stages will be found after one another
- * here later. Currently only one stage per name is returned.
+ * here later. Currently only one stage per name is returned.
*
* @return The index entries sorted
*/
@@ -896,7 +897,7 @@ int longestCommonPath(String[] a, String[] b) {
* @throws UnsupportedEncodingException
*/
public Entry getEntry(String path) throws UnsupportedEncodingException {
- return (Entry) entries.get(Repository.gitInternalSlash(path.getBytes("ISO-8859-1")));
+ return (Entry) entries.get(Repository.gitInternalSlash(Constants.encode(path)));
}
/**
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Tree.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Tree.java
index 25a9a71..0ecd04d 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Tree.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Tree.java
@@ -44,6 +44,7 @@
import org.spearce.jgit.errors.CorruptObjectException;
import org.spearce.jgit.errors.EntryExistsException;
import org.spearce.jgit.errors.MissingObjectException;
+import org.spearce.jgit.util.RawParseUtils;
/**
* A representation of a Git tree entry. A Tree is a directory in Git.
@@ -251,7 +252,7 @@ public void unload() {
* @throws IOException
*/
public FileTreeEntry addFile(final String name) throws IOException {
- return addFile(Repository.gitInternalSlash(name.getBytes(Constants.CHARACTER_ENCODING)), 0);
+ return addFile(Repository.gitInternalSlash(Constants.encode(name)), 0);
}
/**
@@ -281,8 +282,7 @@ public FileTreeEntry addFile(final byte[] s, final int offset)
final byte[] newName = substring(s, offset, slash);
if (p >= 0)
- throw new EntryExistsException(new String(newName,
- Constants.CHARACTER_ENCODING));
+ throw new EntryExistsException(RawParseUtils.decode(newName));
else if (slash < s.length) {
final Tree t = new Tree(this, newName);
insertEntry(p, t);
@@ -304,7 +304,7 @@ else if (slash < s.length) {
* @throws IOException
*/
public Tree addTree(final String name) throws IOException {
- return addTree(Repository.gitInternalSlash(name.getBytes(Constants.CHARACTER_ENCODING)), 0);
+ return addTree(Repository.gitInternalSlash(Constants.encode(name)), 0);
}
/**
@@ -332,8 +332,7 @@ public Tree addTree(final byte[] s, final int offset) throws IOException {
final byte[] newName = substring(s, offset, slash);
if (p >= 0)
- throw new EntryExistsException(new String(newName,
- Constants.CHARACTER_ENCODING));
+ throw new EntryExistsException(RawParseUtils.decode(newName));
final Tree t = new Tree(this, newName);
insertEntry(p, t);
@@ -355,8 +354,7 @@ public void addEntry(final TreeEntry e) throws IOException {
e.attachParent(this);
insertEntry(p, e);
} else {
- throw new EntryExistsException(new String(e.getNameUTF8(),
- Constants.CHARACTER_ENCODING));
+ throw new EntryExistsException(e.getName());
}
}
@@ -450,7 +448,7 @@ public boolean existsBlob(String path) throws IOException {
}
private TreeEntry findMember(final String s, byte slast) throws IOException {
- return findMember(Repository.gitInternalSlash(s.getBytes(Constants.CHARACTER_ENCODING)), slast, 0);
+ return findMember(Repository.gitInternalSlash(Constants.encode(s)), slast, 0);
}
private TreeEntry findMember(final byte[] s, final byte slast, final int offset)
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/TreeEntry.java b/org.spearce.jgit/src/org/spearce/jgit/lib/TreeEntry.java
index 85dda1d..c95863c 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/TreeEntry.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/TreeEntry.java
@@ -39,9 +39,9 @@
package org.spearce.jgit.lib;
import java.io.IOException;
-import java.io.UnsupportedEncodingException;
import org.spearce.jgit.lib.GitIndex.Entry;
+import org.spearce.jgit.util.RawParseUtils;
/**
* This class represents an entry in a tree, like a blob or another tree.
@@ -126,13 +126,9 @@ public Repository getRepository() {
* @return the name of this entry.
*/
public String getName() {
- try {
- return nameUTF8 != null ? new String(nameUTF8,
- Constants.CHARACTER_ENCODING) : null;
- } catch (UnsupportedEncodingException uee) {
- throw new RuntimeException("JVM doesn't support "
- + Constants.CHARACTER_ENCODING, uee);
- }
+ if (nameUTF8 != null)
+ return RawParseUtils.decode(nameUTF8);
+ return null;
}
/**
@@ -142,7 +138,7 @@ public String getName() {
* @throws IOException
*/
public void rename(final String n) throws IOException {
- rename(n.getBytes(Constants.CHARACTER_ENCODING));
+ rename(Constants.encode(n));
}
/**
diff --git a/org.spearce.jgit/src/org/spearce/jgit/util/RawParseUtils.java b/org.spearce.jgit/src/org/spearce/jgit/util/RawParseUtils.java
index 6c0e339..4b96439 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/util/RawParseUtils.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/util/RawParseUtils.java
@@ -379,6 +379,38 @@ public static PersonIdent parsePersonIdent(final byte[] raw, final int nameB) {
}
/**
+ * Decode a buffer under UTF-8, if possible.
+ *
+ * If the byte stream cannot be decoded that way, the platform default is tried
+ * and if that too fails, the fail-safe ISO-8859-1 encoding is tried.
+ *
+ * @param buffer
+ * buffer to pull raw bytes from.
+ * @return a string representation of the range <code>[start,end)</code>,
+ * after decoding the region through the specified character set.
+ */
+ public static String decode(final byte[] buffer) {
+ return decode(Constants.CHARSET, buffer, 0, buffer.length);
+ }
+
+ /**
+ * Decode a buffer under the specified character set if possible.
+ *
+ * If the byte stream cannot be decoded that way, the platform default is tried
+ * and if that too fails, the fail-safe ISO-8859-1 encoding is tried.
+ *
+ * @param cs
+ * character set to use when decoding the buffer.
+ * @param buffer
+ * buffer to pull raw bytes from.
+ * @return a string representation of the range <code>[start,end)</code>,
+ * after decoding the region through the specified character set.
+ */
+ public static String decode(final Charset cs, final byte[] buffer) {
+ return decode(cs, buffer, 0, buffer.length);
+ }
+
+ /**
* Decode a region of the buffer under the specified character set if possible.
*
* If the byte stream cannot be decoded that way, the platform default is tried
--
1.6.0.2.308.gef4a
^ permalink raw reply related
* [PATCH] Teach/Fix -q/-v to pull/fetch
From: Tuncer Ayaz @ 2008-10-19 18:17 UTC (permalink / raw)
To: git
After fixing clone -q I noticed that pull -q does not do what
it's supposed to do and implemented --quiet/--verbose by
adding it to builtin-merge and fixing two places in builtin-fetch.
I have not touched/adjusted contrib/completion/git-completion.bash
but can take a look if wanted. I think it already needs one or two
adjustments caused by recent --OPTIONS changes in master.
I've tested the following invocations with the below changes applied:
$ git pull
$ git pull -q
$ git pull -v
This is the next attempt trying to incorporate Junio's
suggestions and I'm not sure about the following:
1) having the same option callback function in both modules
2) my adaption of the following two lines from
builtin-fetch.c to the new verbosity option:
if (verbosity == VERBOSE)
transport->verbose = 1;
if (verbosity == QUIET)
transport->verbose = -1;
3) my usage of OPTION_CALLBACK. therefore please
correct me if I did it wrong or my cb fun has an
obvious defect. it may very well have one :)
Signed-off-by: Tuncer Ayaz <tuncer.ayaz@gmail.com>
---
Documentation/merge-options.txt | 8 ++++++++
builtin-fetch.c | 35 +++++++++++++++++++++++++----------
builtin-merge.c | 36 +++++++++++++++++++++++++++++-------
git-pull.sh | 10 ++++++++--
4 files changed, 70 insertions(+), 19 deletions(-)
diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt
index 007909a..427cdef 100644
--- a/Documentation/merge-options.txt
+++ b/Documentation/merge-options.txt
@@ -1,3 +1,11 @@
+-q::
+--quiet::
+ Operate quietly.
+
+-v::
+--verbose::
+ Be verbose.
+
--stat::
Show a diffstat at the end of the merge. The diffstat is also
controlled by the configuration option merge.stat.
diff --git a/builtin-fetch.c b/builtin-fetch.c
index ee93d3a..717e833 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -22,16 +22,31 @@ enum {
TAGS_SET = 2
};
-static int append, force, keep, update_head_ok, verbose, quiet;
+static int append, force, keep, update_head_ok;
static int tags = TAGS_DEFAULT;
static const char *depth;
static const char *upload_pack;
static struct strbuf default_rla = STRBUF_INIT;
static struct transport *transport;
+static enum { QUIET, NORMAL, VERBOSE } verbosity = NORMAL;
+
+static int option_parse_verbosity(const struct option *opt,
+ const char *arg, int unset)
+{
+ if (!strcmp("quiet", opt->long_name))
+ verbosity = QUIET;
+ else if (!strcmp("verbose", opt->long_name))
+ verbosity = VERBOSE;
+ return 0;
+}
static struct option builtin_fetch_options[] = {
- OPT__QUIET(&quiet),
- OPT__VERBOSE(&verbose),
+ { OPTION_CALLBACK, 'q', "quiet", NULL, NULL,
+ "operate quietly",
+ PARSE_OPT_NOARG, option_parse_verbosity },
+ { OPTION_CALLBACK, 'v', "verbose", NULL, NULL,
+ "be verbose",
+ PARSE_OPT_NOARG, option_parse_verbosity },
OPT_BOOLEAN('a', "append", &append,
"append to .git/FETCH_HEAD instead of overwriting"),
OPT_STRING(0, "upload-pack", &upload_pack, "PATH",
@@ -192,7 +207,6 @@ static int s_update_ref(const char *action,
static int update_local_ref(struct ref *ref,
const char *remote,
- int verbose,
char *display)
{
struct commit *current = NULL, *updated;
@@ -210,7 +224,7 @@ static int update_local_ref(struct ref *ref,
die("object %s not found", sha1_to_hex(ref->new_sha1));
if (!hashcmp(ref->old_sha1, ref->new_sha1)) {
- if (verbose)
+ if (verbosity == VERBOSE)
sprintf(display, "= %-*s %-*s -> %s", SUMMARY_WIDTH,
"[up to date]", REFCOL_WIDTH, remote,
pretty_ref);
@@ -366,18 +380,19 @@ static int store_updated_refs(const char *url, const char *remote_name,
note);
if (ref)
- rc |= update_local_ref(ref, what, verbose, note);
+ rc |= update_local_ref(ref, what, note);
else
sprintf(note, "* %-*s %-*s -> FETCH_HEAD",
SUMMARY_WIDTH, *kind ? kind : "branch",
REFCOL_WIDTH, *what ? what : "HEAD");
if (*note) {
- if (!shown_url) {
+ if (verbosity > QUIET && !shown_url) {
fprintf(stderr, "From %.*s\n",
url_len, url);
shown_url = 1;
}
- fprintf(stderr, " %s\n", note);
+ if (verbosity > QUIET)
+ fprintf(stderr, " %s\n", note);
}
}
fclose(fp);
@@ -622,9 +637,9 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
remote = remote_get(argv[0]);
transport = transport_get(remote, remote->url[0]);
- if (verbose >= 2)
+ if (verbosity == VERBOSE)
transport->verbose = 1;
- if (quiet)
+ if (verbosity == QUIET)
transport->verbose = -1;
if (upload_pack)
set_option(TRANS_OPT_UPLOADPACK, upload_pack);
diff --git a/builtin-merge.c b/builtin-merge.c
index 5e2b7f1..6966831 100644
--- a/builtin-merge.c
+++ b/builtin-merge.c
@@ -50,6 +50,7 @@ static unsigned char head[20], stash[20];
static struct strategy **use_strategies;
static size_t use_strategies_nr, use_strategies_alloc;
static const char *branch;
+static enum { QUIET, NORMAL, VERBOSE } verbosity = NORMAL;
static struct strategy all_strategy[] = {
{ "recursive", DEFAULT_TWOHEAD | NO_TRIVIAL },
@@ -151,7 +152,23 @@ static int option_parse_n(const struct option *opt,
return 0;
}
+static int option_parse_verbosity(const struct option *opt,
+ const char *arg, int unset)
+{
+ if (!strcmp("quiet", opt->long_name))
+ verbosity = QUIET;
+ else if (!strcmp("verbose", opt->long_name))
+ verbosity = VERBOSE;
+ return 0;
+}
+
static struct option builtin_merge_options[] = {
+ { OPTION_CALLBACK, 'q', "quiet", NULL, NULL,
+ "operate quietly",
+ PARSE_OPT_NOARG, option_parse_verbosity },
+ { OPTION_CALLBACK, 'v', "verbose", NULL, NULL,
+ "be verbose",
+ PARSE_OPT_NOARG, option_parse_verbosity },
{ OPTION_CALLBACK, 'n', NULL, NULL, NULL,
"do not show a diffstat at the end of the merge",
PARSE_OPT_NOARG, option_parse_n },
@@ -249,7 +266,8 @@ static void restore_state(void)
/* This is called when no merge was necessary. */
static void finish_up_to_date(const char *msg)
{
- printf("%s%s\n", squash ? " (nothing to squash)" : "", msg);
+ if (verbosity > QUIET)
+ printf("%s%s\n", squash ? " (nothing to squash)" : "", msg);
drop_save();
}
@@ -330,14 +348,15 @@ static void finish(const unsigned char *new_head, const char *msg)
if (!msg)
strbuf_addstr(&reflog_message, getenv("GIT_REFLOG_ACTION"));
else {
- printf("%s\n", msg);
+ if (verbosity > QUIET)
+ printf("%s\n", msg);
strbuf_addf(&reflog_message, "%s: %s",
getenv("GIT_REFLOG_ACTION"), msg);
}
if (squash) {
squash_message();
} else {
- if (!merge_msg.len)
+ if (verbosity > QUIET && !merge_msg.len)
printf("No merge message -- not updating HEAD\n");
else {
const char *argv_gc_auto[] = { "gc", "--auto", NULL };
@@ -871,6 +890,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
argc = parse_options(argc, argv, builtin_merge_options,
builtin_merge_usage, 0);
+ if (verbosity > QUIET)
+ show_diffstat = 0;
if (squash) {
if (!allow_fast_forward)
@@ -1012,10 +1033,11 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
strcpy(hex, find_unique_abbrev(head, DEFAULT_ABBREV));
- printf("Updating %s..%s\n",
- hex,
- find_unique_abbrev(remoteheads->item->object.sha1,
- DEFAULT_ABBREV));
+ if (verbosity > QUIET)
+ printf("Updating %s..%s\n",
+ hex,
+ find_unique_abbrev(remoteheads->item->object.sha1,
+ DEFAULT_ABBREV));
strbuf_addstr(&msg, "Fast forward");
if (have_message)
strbuf_addstr(&msg,
diff --git a/git-pull.sh b/git-pull.sh
index 75c3610..8e25d44 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -16,6 +16,7 @@ cd_to_toplevel
test -z "$(git ls-files -u)" ||
die "You are in the middle of a conflicted merge."
+quiet= verbose=
strategy_args= no_stat= no_commit= squash= no_ff= log_arg=
curr_branch=$(git symbolic-ref -q HEAD)
curr_branch_short=$(echo "$curr_branch" | sed "s|refs/heads/||")
@@ -23,6 +24,10 @@ rebase=$(git config --bool branch.$curr_branch_short.rebase)
while :
do
case "$1" in
+ -q|--quiet)
+ quiet=-q ;;
+ -v|--verbose)
+ verbose=-v ;;
-n|--no-stat|--no-summary)
no_stat=-n ;;
--stat|--summary)
@@ -121,7 +126,7 @@ test true = "$rebase" && {
"refs/remotes/$origin/$reflist" 2>/dev/null)"
}
orig_head=$(git rev-parse --verify HEAD 2>/dev/null)
-git fetch --update-head-ok "$@" || exit 1
+git fetch $verbose $quiet --update-head-ok "$@" || exit 1
curr_head=$(git rev-parse --verify HEAD 2>/dev/null)
if test "$curr_head" != "$orig_head"
@@ -181,5 +186,6 @@ merge_name=$(git fmt-merge-msg $log_arg <"$GIT_DIR/FETCH_HEAD") || exit
test true = "$rebase" &&
exec git-rebase $strategy_args --onto $merge_head \
${oldremoteref:-$merge_head}
-exec git-merge $no_stat $no_commit $squash $no_ff $log_arg $strategy_args \
+exec git-merge $quiet $verbose $no_stat $no_commit \
+ $squash $no_ff $log_arg $strategy_args \
"$merge_name" HEAD $merge_head
--
1.6.0.2.GIT
^ permalink raw reply related
* [PATCH, RFC] diff: add option to show context between close chunks
From: René Scharfe @ 2008-10-19 17:59 UTC (permalink / raw)
To: Git Mailing List; +Cc: Davide Libenzi
This patch adds a new diff option, --inter-chunk-context. It can be
used to show the context in gaps between chunks, thereby creating a
big chunk out of two close chunks, in order to have an unbroken
context, making reviews easier.
With --inter-chunk-context=1, patches have the same number of lines
as without the option, as only the chunk header is replaced by the
context line it was shadowing.
You can use commit b0b44bc7b26c8c4b4221a377ce6ba174b843cb8d in the
git repo to try out this option; there's a chunk in transport.c
which is just one line away from the next. (I found this option
helpful in reviewing my own patch before sending. :)
I think it makes sense to make 1, or even 3, the default for this
option for all commands that create patches intended for human
consumption. The patch keeps the default at 0, though.
There are downsides, of course: values higher than 1 potentially make
the resulting patch longer. More context means a higher probability
of (perhaps unnecessary) merge conflicts.
Comments?
---
Documentation/diff-options.txt | 4 ++
diff.c | 4 ++
diff.h | 1 +
t/t4030-diff-inter-chunk-context.sh | 75 +++++++++++++++++++++++++++++++++++
xdiff/xdiff.h | 1 +
xdiff/xemit.c | 3 +-
6 files changed, 87 insertions(+), 1 deletions(-)
create mode 100755 t/t4030-diff-inter-chunk-context.sh
diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index c62b45c..e0c6d8c 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -215,6 +215,10 @@ endif::git-format-patch[]
-w::
Shorthand for "--ignore-all-space".
+--inter-chunk-context=<lines>::
+ Show the context between diff chunks, up to the specified number
+ of lines, thereby fusing chunks that are close to each other.
+
--exit-code::
Make the program exit with codes similar to diff(1).
That is, it exits with 1 if there were differences and
diff --git a/diff.c b/diff.c
index 1c6be89..4a3b486 100644
--- a/diff.c
+++ b/diff.c
@@ -1594,6 +1594,7 @@ static void builtin_diff(const char *name_a,
ecbdata.file = o->file;
xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
xecfg.ctxlen = o->context;
+ xecfg.interchunkctxlen = o->interchunkcontext;
xecfg.flags = XDL_EMIT_FUNCNAMES;
if (pe)
xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags);
@@ -2677,6 +2678,9 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
options->b_prefix = arg + 13;
else if (!strcmp(arg, "--no-prefix"))
options->a_prefix = options->b_prefix = "";
+ else if (opt_arg(arg, '\0', "inter-chunk-context",
+ &options->interchunkcontext))
+ ;
else if (!prefixcmp(arg, "--output=")) {
options->file = fopen(arg + strlen("--output="), "w");
options->close_file = 1;
diff --git a/diff.h b/diff.h
index a49d865..6003024 100644
--- a/diff.h
+++ b/diff.h
@@ -77,6 +77,7 @@ struct diff_options {
const char *a_prefix, *b_prefix;
unsigned flags;
int context;
+ int interchunkcontext;
int break_opt;
int detect_rename;
int skip_stat_unmatch;
diff --git a/t/t4030-diff-inter-chunk-context.sh b/t/t4030-diff-inter-chunk-context.sh
new file mode 100755
index 0000000..448f1b9
--- /dev/null
+++ b/t/t4030-diff-inter-chunk-context.sh
@@ -0,0 +1,75 @@
+#!/bin/sh
+
+test_description='diff chunk merging'
+
+. ./test-lib.sh
+
+f() {
+ i=1
+ echo $1
+ while test $i -le $2
+ do
+ echo $i
+ i=$(expr $i + 1)
+ done
+ echo $3
+}
+
+test_expect_success 'setup' '
+ f a 1 b >f1 &&
+ f a 2 b >f2 &&
+ f a 3 b >f3 &&
+ git add f1 f2 f3 &&
+ git commit -q -m. f1 f2 f3 &&
+ f x 1 y >f1 &&
+ f x 2 y >f2 &&
+ f x 3 y >f3
+'
+
+t() {
+ case "$2" in
+ '') cmd="diff -U$1" ;;
+ *) cmd="diff -U$1 --inter-chunk-context=$2" ;;
+ esac
+ label="$cmd, $3 common $4"
+
+ test_expect_success "$label: count chunks ($5)" "
+ test $(git $cmd f$3 | grep '^@@ ' | wc -l) = $5
+ "
+
+ expected="expected.$1.$3.$5"
+ test -f $expected &&
+ test_expect_success "$label: check output" "
+ git $cmd f$3 >actual &&
+ test_cmp $expected actual
+ "
+}
+
+cat <<EOF >expected.0.1.1 || exit 1
+diff --git a/f1 b/f1
+index f1e80ce..ae397d0 100644
+--- a/f1
++++ b/f1
+@@ -1,3 +1,3 @@
+-a
++x
+ 1
+-b
++y
+EOF
+
+# ctx intrctx common lines chunks
+t 0 '' 1 line 2
+t 0 0 1 line 2
+t 0 1 1 line 1
+t 0 2 1 line 1
+t 0 '' 2 lines 2
+t 0 0 2 lines 2
+t 0 1 2 lines 2
+t 0 2 2 lines 1
+t 1 '' 3 lines 2
+t 1 0 3 lines 2
+t 1 1 3 lines 1
+t 1 2 3 lines 1
+
+test_done
diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h
index deebe02..d8f14e6 100644
--- a/xdiff/xdiff.h
+++ b/xdiff/xdiff.h
@@ -84,6 +84,7 @@ typedef long (*find_func_t)(const char *line, long line_len, char *buffer, long
typedef struct s_xdemitconf {
long ctxlen;
+ long interchunkctxlen;
unsigned long flags;
find_func_t find_func;
void *find_func_priv;
diff --git a/xdiff/xemit.c b/xdiff/xemit.c
index d3d9c84..3bf2581 100644
--- a/xdiff/xemit.c
+++ b/xdiff/xemit.c
@@ -60,9 +60,10 @@ static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *
*/
static xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg) {
xdchange_t *xch, *xchp;
+ long max_common = 2 * xecfg->ctxlen + xecfg->interchunkctxlen;
for (xchp = xscr, xch = xscr->next; xch; xchp = xch, xch = xch->next)
- if (xch->i1 - (xchp->i1 + xchp->chg1) > 2 * xecfg->ctxlen)
+ if (xch->i1 - (xchp->i1 + xchp->chg1) > max_common)
break;
return xchp;
--
1.6.0.2.287.g3791f
^ permalink raw reply related
* Re: [PATCH/RFR&A] Do not rename read-only files during a push
From: Johannes Sixt @ 2008-10-19 17:41 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Petr Baudis, Shawn O. Pearce
In-Reply-To: <7v63np83mw.fsf@gitster.siamese.dyndns.org>
On Sonntag, 19. Oktober 2008, Junio C Hamano wrote:
> From: Petr Baudis <pasky@suse.cz>
>
> Win32 does not allow renaming read-only files (at least on a Samba
> share), making push into a local directory to fail. Thus, defer
> the chmod() call in index-pack.c:final() only after
> move_temp_to_file() was called.
Concerning the Win32 aspect of this patch:
Acked-by: Johannes Sixt <johannes.sixt@telecom.at>
-- Hannes
^ permalink raw reply
* Re: [JGIT PATCH] Encode/decode index and tree entries using UTF-8
From: Shawn O. Pearce @ 2008-10-19 17:14 UTC (permalink / raw)
To: Robin Rosenberg; +Cc: git
In-Reply-To: <200810191529.43439.robin.rosenberg.lists@dewire.com>
Robin Rosenberg <robin.rosenberg.lists@dewire.com> wrote:
> Decoding uses the same strategy as for commit messages and other string
> entities. Encoding is always done in UTF-8. This is incompatible with
> Git for non-unicode unices, but it leads to the expected behavior on
> Windows and cross-locale sharing of repositories.
FWIW I think this is a good idea.
> Inpired by the recent thread on the gitml, I decideed to clean up jgit a little. I
> know the GitIndex is soon to be obsoleted, but it it still the class that does
> the dirty work when committing in Egit and the changes are fairly simple
> anyway.
Yup, I agree.
I mostly agree with the patch, but we have a utility function you
are missing using:
> @@ -300,11 +302,11 @@ static boolean File_hasExecute() {
> return FS.INSTANCE.supportsExecute();
> }
>
> - static byte[] makeKey(File wd, File f) {
> + static byte[] makeKey(File wd, File f) throws IOException {
> if (!f.getPath().startsWith(wd.getPath()))
> throw new Error("Path is not in working dir");
> String relName = Repository.stripWorkDir(wd, f);
> - return relName.getBytes();
> + return relName.getBytes(Constants.CHARACTER_ENCODING);
> }
Instead of "relName.getBytes(Constants.CHARACTER_ENCODING)" use
"Constants.encode(relName)". Its shorter and faster.
> @@ -591,7 +593,7 @@ public String toString() {
> * @return path name for this entry
> */
> public String getName() {
> - return new String(name);
> + return RawParseUtils.decode(Constants.CHARSET, name, 0, name.length);
Heh. That's actually a common idiom. We probably should add:
String decode(final byte[] arr) {
return decode(Constants.CHARSET, arr, 0, arr.length);
}
to RawParseUtils to make these decode whole array calls easier
to make.
I think you should squash this into your patch, and fix up the
getBytes and decode calls as I noted above before we apply this.
diff --git a/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCacheEntry.java b/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCacheEntry.java
index cc683d7..913f3ae 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCacheEntry.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCacheEntry.java
@@ -42,7 +42,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.nio.ByteBuffer;
import java.util.Arrays;
import org.spearce.jgit.lib.AnyObjectId;
@@ -50,6 +49,7 @@
import org.spearce.jgit.lib.FileMode;
import org.spearce.jgit.lib.ObjectId;
import org.spearce.jgit.util.NB;
+import org.spearce.jgit.util.RawParseUtils;
/**
* A single file (or stage of a file) in a {@link DirCache}.
@@ -405,7 +405,7 @@ public void setObjectIdFromRaw(final byte[] bs, final int p) {
* returned string.
*/
public String getPathString() {
- return Constants.CHARSET.decode(ByteBuffer.wrap(path)).toString();
+ return RawParseUtils.decode(path);
}
/**
diff --git a/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCacheTree.java b/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCacheTree.java
index 26b6348..589894a 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCacheTree.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCacheTree.java
@@ -39,7 +39,6 @@
import java.io.IOException;
import java.io.OutputStream;
-import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Comparator;
@@ -251,8 +250,7 @@ ObjectId getObjectId() {
* @return name of the tree. This does not contain any '/' characters.
*/
public String getNameString() {
- final ByteBuffer bb = ByteBuffer.wrap(encodedName);
- return Constants.CHARSET.decode(bb).toString();
+ return RawParseUtils.decode(encodedName);
}
/**
diff --git a/org.spearce.jgit/src/org/spearce/jgit/util/RawParseUtils.java b/org.spearce.jgit/src/org/spearce/jgit/util/RawParseUtils.java
index 6c0e339..2519f19 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/util/RawParseUtils.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/util/RawParseUtils.java
@@ -379,6 +379,21 @@ public static PersonIdent parsePersonIdent(final byte[] raw, final int nameB) {
}
/**
+ * Decode a region of the buffer from the default character set (UTF-8).
+ *
+ * If the byte stream cannot be decoded that way, the platform default is
+ * tried and if that too fails, the fail-safe ISO-8859-1 encoding is tried.
+ *
+ * @param buffer
+ * buffer to pull raw bytes from.
+ * @return a string representation of the entire buffer, after decoding the
+ * region through the specified character set.
+ */
+ public static String decode(final byte[] buffer) {
+ return decode(Constants.CHARSET, buffer, 0, buffer.length);
+ }
+
+ /**
* Decode a region of the buffer under the specified character set if possible.
*
* If the byte stream cannot be decoded that way, the platform default is tried
--
Shawn.
^ permalink raw reply related
* Re: [PATCH/RFR&A] Do not rename read-only files during a push
From: Shawn O. Pearce @ 2008-10-19 17:02 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Petr Baudis, Johannes Sixt, git
In-Reply-To: <7v63np83mw.fsf@gitster.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> wrote:
> This is on the "merged to 'master' soon" list, but has a small amend by me
> (namely, chmod of final pack is done only when we are writing the final
> pack, i.e. reading from stdin) to fix breakages observed in tests. It
> would be nice to get a final Ack before moving it to 'master'.
Looks fine to me.
> From: Petr Baudis <pasky@suse.cz>
>
> Win32 does not allow renaming read-only files (at least on a Samba
> share), making push into a local directory to fail. Thus, defer
> the chmod() call in index-pack.c:final() only after
> move_temp_to_file() was called.
>
> Signed-off-by: Petr Baudis <pasky@suse.cz>
> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
> ---
> index-pack.c | 5 +++--
> 1 files changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/index-pack.c b/index-pack.c
> index d3a4d31..aec11cb 100644
> --- a/index-pack.c
> +++ b/index-pack.c
> @@ -790,7 +790,6 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
> err = close(output_fd);
> if (err)
> die("error while closing pack file: %s", strerror(errno));
> - chmod(curr_pack_name, 0444);
> }
>
> if (keep_msg) {
> @@ -824,8 +823,9 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
> if (move_temp_to_file(curr_pack_name, final_pack_name))
> die("cannot store pack file");
> }
> + if (from_stdin)
> + chmod(final_pack_name, 0444);
>
> - chmod(curr_index_name, 0444);
> if (final_index_name != curr_index_name) {
> if (!final_index_name) {
> snprintf(name, sizeof(name), "%s/pack/pack-%s.idx",
> @@ -835,6 +835,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
> if (move_temp_to_file(curr_index_name, final_index_name))
> die("cannot store index file");
> }
> + chmod(final_index_name, 0444);
>
> if (!from_stdin) {
> printf("%s\n", sha1_to_hex(sha1));
> --
> 1.6.0.2.767.g8f0e
>
--
Shawn.
^ permalink raw reply
* [PATCH v2] Add command line option --chdir/-C to allow setting git process work directory.
From: Maciej Pasternacki @ 2008-10-19 16:18 UTC (permalink / raw)
To: git; +Cc: Jeff King
When "git pull" is ran outside of work tree, it is unable to update work tree
with pulled changes; specifying --git-dir and --work-tree does not help here
because "cd_to_toplevel" call in git-pull occurs after "require_work_tree";
changing order may break the commend if there is no working tree. Some more
commands behave in a similar way.
In my project, I need to call "git pull" from outside of work tree, but I need
it to update the work tree. It seems to require doing chdir() before running
git, but this is problematic thing to do in the calling program because of
portability issues. Proper solution seems to be providing -C / --chdir command
line option, similar to this of Make, that would make main git program perform
chdir() to specified directory before running the specific command. This would
make using git from outside programs much more straightforward.
This patch provides -C and --chdir command line options that behave as
described above.
Signed-off-by: Maciej Pasternacki <maciej@pasternacki.net>
---
Documentation/git.txt | 6 +++++-
git.c | 19 ++++++++++++++++++-
2 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/Documentation/git.txt b/Documentation/git.txt
index df420ae..6676d68 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -12,7 +12,7 @@ SYNOPSIS
'git' [--version] [--exec-path[=GIT_EXEC_PATH]]
[-p|--paginate|--no-pager]
[--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE]
- [--help] COMMAND [ARGS]
+ [-C DIRECTORY|--chdir=DIRECTORY] [--help] COMMAND [ARGS]
DESCRIPTION
-----------
@@ -185,6 +185,10 @@ help ...`.
environment is not set, it is set to the current working
directory.
+-C <directory>::
+--chdir=<directory>::
+ Change working directory before doing anything.
+
FURTHER DOCUMENTATION
---------------------
diff --git a/git.c b/git.c
index 89feb0b..c63d754 100644
--- a/git.c
+++ b/git.c
@@ -4,7 +4,7 @@
#include "quote.h"
const char git_usage_string[] =
- "git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]";
+ "git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [-C DIR|--chdir=DIR] [--help] COMMAND [ARGS]";
const char git_more_info_string[] =
"See 'git help COMMAND' for more information on a specific command.";
@@ -115,6 +115,23 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
setenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir, sizeof(git_dir)), 0);
if (envchanged)
*envchanged = 1;
+ } else if (!strcmp(cmd, "-C") || !strcmp(cmd, "--chdir")) {
+ if (*argc < 2) {
+ fprintf(stderr, "No directory given for --chdir or -C.\n" );
+ usage(git_usage_string);
+ }
+ if (chdir((*argv)[1])) {
+ fprintf(stderr, "Cannot change directory to %s: %s\n", (*argv)[1], strerror(errno));
+ usage(git_usage_string);
+ }
+ (*argv)++;
+ (*argc)--;
+ handled++;
+ } else if (!prefixcmp(cmd,"--chdir=")) {
+ if (chdir(cmd+8)) {
+ fprintf(stderr, "Cannot change directory to %s: %s\n", cmd+8, strerror(errno));
+ usage(git_usage_string);
+ }
} else {
fprintf(stderr, "Unknown option: %s\n", cmd);
usage(git_usage_string);
--
1.6.0.1
^ permalink raw reply related
* [PATCH] Documentation: Spelling fix
From: Fredrik Skolmli @ 2008-10-19 16:09 UTC (permalink / raw)
To: gitster; +Cc: git
Signed-off-by: Fredrik Skolmli <fredrik@frsk.net>
---
Documentation/git-checkout.txt | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index 2b344e1..ea05a7a 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -88,7 +88,7 @@ This would tell us to use "hack" as the local branch when branching
off of "origin/hack" (or "remotes/origin/hack", or even
"refs/remotes/origin/hack"). If the given name has no slash, or the above
guessing results in an empty name, the guessing is aborted. You can
-exlicitly give a name with '-b' in such a case.
+explicitly give a name with '-b' in such a case.
--no-track::
Ignore the branch.autosetupmerge configuration variable.
--
1.5.6.5
^ permalink raw reply related
* Re: [PATCH] -C/--chdir command line option
From: Maciej Pasternacki @ 2008-10-19 15:24 UTC (permalink / raw)
To: Jeff King; +Cc: git
In-Reply-To: <20081019141634.GA8997@coredump.intra.peff.net>
On 2008-10-19, at 16:16, Jeff King wrote:
> Though I am not clear from your original description if that is even
> what you want. It sounds like you might be doing:
>
> git -C /chdir/path --git-dir=/back/to/where/I/was
>
> in which case I think work-tree _is_ a better fit.
No. I have a regular "git clone"'d work tree inside some "shelf"
directory containing many repos (not only from git), and I'd like to
pull changes into this work tree. As simple as "cvs up". But -- I
don't want to chdir() there myself, and I had no problem with cvs, svn
and darcs (didn't do other VC systems yet). So, -C would do exactly
what I need.
>>> Also, the envchanged flag should probably be set, as for the git-dir
>>> and work-tree options.
>>
>> OK. I thought it means literally environment change, as in setenv().
>
> It is really used to tell the options parser for aliases that some
> options which change the operating environment should not be used in
> an
> alias. I.e., something like:
>
> git config alias.foo "--git-dir=/path/to/whatever log"
>
> isn't allowed, because we have already done some work on setting up
> the
> git-dir at this point. IMHO, this is a limitation of the current
> approach to setting up the environment, but fixing it would be
> nontrivial.
>
> I'm not 100% sure that doing a chdir should be disallowed in this
> instance, but I suspect it would cause problems. I think it is
> better in
> this instance to be conservative and disallow it in aliases.
In this case, I think envchanged should not be set -- I would expect -
C dir to work *exactly* like "cd dir && git ...", including
configuration, environment variables and so on. OTOH, option like "--
no-env" may be useful in my case -- I want git to behave consistently
on users' machines, regardless of their configuration. This, however,
is only a minor issue.
Regards,
Maciej.
--
-><- Maciej Pasternacki -><- http://www.pasternacki.net/ -><-
^ permalink raw reply
* [RFC PATCH v3] Documentation: add manpage about workflows
From: Thomas Rast @ 2008-10-19 15:20 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, santi, Dmitry Potapov
In-Reply-To: <7v8wsyortf.fsf@gitster.siamese.dyndns.org>
This attempts to make a manpage about workflows that is both handy to
point people at it and as a beginner's introduction.
Signed-off-by: Thomas Rast <trast@student.ethz.ch>
---
> > +Integration branches
> > +~~~~~~~~~~~~~~~~~~~~
>
> Nomenclature. I think we use the word "integration branches" to mean the
> stable branches such as maint/master/next, not the ones you use for
> throw-away test merges.
I renamed those, and now call 'pu' a "throw-away integration branch",
which is sort of unwieldy but I can't think of a good short name.
Full interdiff follows, as before.
Documentation/Makefile | 2 +-
Documentation/gitworkflows.txt | 364 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 365 insertions(+), 1 deletions(-)
diff --git a/Documentation/Makefile b/Documentation/Makefile
index ded0e40..e33ddcb 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -6,7 +6,7 @@ MAN5_TXT=gitattributes.txt gitignore.txt gitmodules.txt githooks.txt \
gitrepository-layout.txt
MAN7_TXT=gitcli.txt gittutorial.txt gittutorial-2.txt \
gitcvs-migration.txt gitcore-tutorial.txt gitglossary.txt \
- gitdiffcore.txt
+ gitdiffcore.txt gitworkflows.txt
MAN_TXT = $(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT)
MAN_XML=$(patsubst %.txt,%.xml,$(MAN_TXT))
diff --git a/Documentation/gitworkflows.txt b/Documentation/gitworkflows.txt
new file mode 100644
index 0000000..7fe9f72
--- /dev/null
+++ b/Documentation/gitworkflows.txt
@@ -0,0 +1,364 @@
+gitworkflows(7)
+===============
+
+NAME
+----
+gitworkflows - An overview of recommended workflows with git
+
+SYNOPSIS
+--------
+git *
+
+
+DESCRIPTION
+-----------
+
+This document attempts to write down and motivate some of the workflow
+elements used for `git.git` itself. Many ideas apply in general,
+though the full workflow is rarely required for smaller projects with
+fewer people involved.
+
+We formulate a set of 'rules' for quick reference, while the prose
+tries to motivate each of them. Do not always take them literally;
+you should value good reasons for your actions higher than manpages
+such as this one.
+
+
+SEPARATE CHANGES
+----------------
+
+As a general rule, you should try to split your changes into small
+logical steps, and commit each of them. They should be consistent,
+working independently of any later commits, pass the test suite, etc.
+This makes the review process much easier, and the history much more
+useful for later inspection and analysis, for example with
+linkgit:git-blame[1] and linkgit:git-bisect[1].
+
+To achieve this, try to split your work into small steps from the very
+beginning. It is always easier to squash a few commits together than
+to split one big commit into several. Don't be afraid of making too
+small or imperfect steps along the way. You can always go back later
+and edit the commits with `git rebase \--interactive` before you
+publish them. You can use `git stash save \--keep-index` to run the
+test suite independent of other uncommitted changes; see the EXAMPLES
+section of linkgit:git-stash[1].
+
+
+MANAGING BRANCHES
+-----------------
+
+There are two main tools that can be used to include changes from one
+branch on another: linkgit:git-merge[1] and
+linkgit:git-cherry-pick[1].
+
+Merges have many advantages, so we try to solve as many problems as
+possible with merges alone. Cherry-picking is still occasionally
+useful; see "Merging upwards" below for an example.
+
+Most importantly, merging works at the branch level, while
+cherry-picking works at the commit level. This means that a merge can
+carry over the changes from 1, 10, or 1000 commits with equal ease,
+which in turn means the workflow scales much better to a large number
+of contributors (and contributions). Merges are also easier to
+understand because a merge commit is a "promise" that all changes from
+all its parents are now included.
+
+There is a tradeoff of course: merges require a more careful branch
+management. The following subsections discuss the important points.
+
+
+Graduation
+~~~~~~~~~~
+
+As a given feature goes from experimental to stable, it also
+"graduates" between the corresponding branches of the software.
+`git.git` uses the following 'integration branches':
+
+* 'maint' tracks the commits that should go into the next "maintenance
+ release", i.e., update of the last released stable version;
+
+* 'master' tracks the commits that should go into the next release;
+
+* 'next' is intended as a testing branch for topics being tested for
+ stability for master.
+
+There is a fourth official branch that is used slightly differently:
+
+* 'pu' (proposed updates) is an integration branch for things that are
+ not quite ready for inclusion yet (see "Integration Branches"
+ below).
+
+Each of the four branches is usually a direct descendant of the one
+above it.
+
+Conceptually, the feature enters at an unstable branch (usually 'next'
+or 'pu'), and "graduates" to 'master' for the next release once it is
+considered stable enough.
+
+
+Merging upwards
+~~~~~~~~~~~~~~~
+
+The "downwards graduation" discussed above cannot be done by actually
+merging downwards, however, since that would merge 'all' changes on
+the unstable branch into the stable one. Hence the following:
+
+.Merge upwards
+[caption="Rule: "]
+=====================================
+Always commit your fixes to the oldest supported branch that require
+them. Then (periodically) merge the integration branches upwards into each
+other.
+=====================================
+
+This gives a very controlled flow of fixes. If you notice that you
+have applied a fix to e.g. 'master' that is also required in 'maint',
+you will need to cherry-pick it (using linkgit:git-cherry-pick[1])
+downwards. This will happen a few times and is nothing to worry about
+unless you do it very frequently.
+
+
+Topic branches
+~~~~~~~~~~~~~~
+
+Any nontrivial feature will require several patches to implement, and
+may get extra bugfixes or improvements during its lifetime.
+
+Committing everything directly on the integration branches leads to many
+problems: Bad commits cannot be undone, so they must be reverted one
+by one, which creates confusing histories and further error potential
+when you forget to revert part of a group of changes. Working in
+parallel mixes up the changes, creating further confusion.
+
+Use of "topic branches" solves these problems. The name is pretty
+self explanatory, with a caveat that comes from the "merge upwards"
+rule above:
+
+.Topic branches
+[caption="Rule: "]
+=====================================
+Make a side branch for every topic (feature, bugfix, ...). Fork it off
+at the oldest integration branch that you will eventually want to merge it
+into.
+=====================================
+
+Many things can then be done very naturally:
+
+* To get the feature/bugfix into an integration branch, simply merge
+ it. If the topic has evolved further in the meantime, merge again.
+ (Note that you do not necessarily have to merge it to the oldest
+ integration branch first. For example, you can first merge a bugfix
+ to 'next', give it some testing time, and merge to 'maint' when you
+ know it is stable.)
+
+* If you find you need new features from the branch 'other' to continue
+ working on your topic, merge 'other' to 'topic'. (However, do not
+ do this "just habitually", see below.)
+
+* If you find you forked off the wrong branch and want to move it
+ "back in time", use linkgit:git-rebase[1].
+
+Note that the last point clashes with the other two: a topic that has
+been merged elsewhere should not be rebased. See the section on
+RECOVERING FROM UPSTREAM REBASE in linkgit:git-rebase[1].
+
+We should point out that "habitually" (regularly for no real reason)
+merging an integration branch into your topics -- and by extension,
+merging anything upstream into anything downstream on a regular basis
+-- is frowned upon:
+
+.Merge to downstream only at well-defined points
+[caption="Rule: "]
+=====================================
+Do not merge to downstream except with a good reason: upstream API
+changes affect your branch; your branch no longer merges to upstream
+cleanly; etc.
+=====================================
+
+Otherwise, the topic that was merged to suddenly contains more than a
+single (well-separated) change. The many resulting small merges will
+greatly clutter up history. Anyone who later investigates the history
+of a file will have to find out whether that merge affected the topic
+in development. An upstream might even inadvertently be merged into a
+"more stable" branch. And so on.
+
+
+Throw-away integration
+~~~~~~~~~~~~~~~~~~~~~~
+
+If you followed the last paragraph, you will now have many small topic
+branches, and occasionally wonder how they interact. Perhaps the
+result of merging them does not even work? But on the other hand, we
+want to avoid merging them anywhere "stable" because such merges
+cannot easily be undone.
+
+The solution, of course, is to make a merge that we can undo: merge
+into a throw-away branch.
+
+.Throw-away integration branches
+[caption="Rule: "]
+=====================================
+To test the interaction of several topics, merge them into a
+throw-away branch. You must never base any work on such a branch!
+=====================================
+
+If you make it (very) clear that this branch is going to be deleted
+right after the testing, you can even publish this branch, for example
+to give the testers a chance to work with it, or other developers a
+chance to see if their in-progress work will be compatible. `git.git`
+has such an official throw-away integration branch called 'pu'.
+
+
+DISTRIBUTED WORKFLOWS
+---------------------
+
+After the last section, you should know how to manage topics. In
+general, you will not be the only person working on the project, so
+you will have to share your work.
+
+Roughly speaking, there are two important workflows: merge and patch.
+The important difference is that the merge workflow can propagate full
+history, including merges, while patches cannot. Both workflows can
+be used in parallel: in `git.git`, only subsystem maintainers use
+the merge workflow, while everyone else sends patches.
+
+Note that the maintainer(s) may impose restrictions, such as
+"Signed-off-by" requirements, that all commits/patches submitted for
+inclusion must adhere to. Consult your project's documentation for
+more information.
+
+
+Merge workflow
+~~~~~~~~~~~~~~
+
+The merge workflow works by copying branches between upstream and
+downstream. Upstream can merge contributions into the official
+history; downstream base their work on the official history.
+
+There are three main tools that can be used for this:
+
+* linkgit:git-push[1] copies your branches to a remote repository,
+ usually to one that can be read by all involved parties;
+
+* linkgit:git-fetch[1] that copies remote branches to your repository;
+ and
+
+* linkgit:git-pull[1] that does fetch and merge in one go.
+
+Note the last point. Do 'not' use 'git-pull' unless you actually want
+to merge the remote branch.
+
+Getting changes out is easy:
+
+.Push/pull: Publishing branches/topics
+[caption="Recipe: "]
+=====================================
+`git push <remote> <branch>` and tell everyone where they can fetch
+from.
+=====================================
+
+You will still have to tell people by other means, such as mail. (Git
+provides the linkgit:request-pull[1] to send preformatted pull
+requests to upstream maintainers to simplify this task.)
+
+If you just want to get the newest copies of the integration branches,
+staying up to date is easy too:
+
+.Push/pull: Staying up to date
+[caption="Recipe: "]
+=====================================
+Use `git fetch <remote>` or `git remote update` to stay up to date.
+=====================================
+
+Then simply fork your topic branches from the stable remotes as
+explained earlier.
+
+If you are a maintainer and would like to merge other people's topic
+branches to the integration branches, they will typically send a
+request to do so by mail. Such a request looks like
+
+-------------------------------------
+Please pull from
+ <url> <branch>
+-------------------------------------
+
+In that case, 'git-pull' can do the fetch and merge in one go, as
+follows.
+
+.Push/pull: Merging remote topics
+[caption="Recipe: "]
+=====================================
+`git pull <url> <branch>`
+=====================================
+
+Occasionally, the maintainer may get merge conflicts when he tries to
+pull changes from downstream. In this case, he can ask downstream to
+do the merge and resolve the conflicts themselves (perhaps they will
+know better how to resolve them). It is one of the rare cases where
+downstream 'should' merge from upstream.
+
+
+Patch workflow
+~~~~~~~~~~~~~~
+
+If you are a contributor that sends changes upstream in the form of
+emails, you should use topic branches as usual (see above). Then use
+linkgit:git-format-patch[1] to generate the corresponding emails
+(highly recommended over manually formatting them because it makes the
+maintainer's life easier).
+
+.format-patch/am: Publishing branches/topics
+[caption="Recipe: "]
+=====================================
+* `git format-patch -M upstream..topic` to turn them into preformatted
+ patch files
+* `git send-email --to=<recipient> <patches>`
+=====================================
+
+See the linkgit:git-format-patch[1] and linkgit:git-send-email[1]
+manpages for further usage notes.
+
+If the maintainer tells you that your patch no longer applies to the
+current upstream, you will have to rebase your topic (you cannot use a
+merge because you cannot format-patch merges):
+
+.format-patch/am: Keeping topics up to date
+[caption="Recipe: "]
+=====================================
+`git pull --rebase <url> <branch>`
+=====================================
+
+You can then fix the conflicts during the rebase. Presumably you have
+not published your topic other than by mail, so rebasing it is not a
+problem.
+
+If you receive such a patch series (as maintainer, or perhaps as a
+reader of the mailing list it was sent to), save the mails to files,
+create a new topic branch and use 'git-am' to import the commits:
+
+.format-patch/am: Importing patches
+[caption="Recipe: "]
+=====================================
+`git am < patch`
+=====================================
+
+One feature worth pointing out is the three-way merge, which can help
+if you get conflicts: `git am -3` will use index information contained
+in patches to figure out the merge base. See linkgit:git-am[1] for
+other options.
+
+
+SEE ALSO
+--------
+linkgit:gittutorial[7],
+linkgit:git-push[1],
+linkgit:git-pull[1],
+linkgit:git-merge[1],
+linkgit:git-rebase[1],
+linkgit:git-format-patch[1],
+linkgit:git-send-email[1],
+linkgit:git-am[1]
+
+GIT
+---
+Part of the linkgit:git[1] suite.
--
tg: (50ea8e5..) t/doc-workflows (depends on: origin/master t/doc-rebase-warn t/doc-rebase-refer)
^ permalink raw reply related
* [Interdiff] [RFC PATCH v3] Documentation: add manpage about workflows
From: Thomas Rast @ 2008-10-19 15:20 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, santi, Dmitry Potapov
In-Reply-To: <1224429622-1548-1-git-send-email-trast@student.ethz.ch>
---
Documentation/gitworkflows.txt | 72 ++++++++++++++++++++-------------------
1 files changed, 37 insertions(+), 35 deletions(-)
diff --git a/Documentation/gitworkflows.txt b/Documentation/gitworkflows.txt
index 037ace5..7fe9f72 100644
--- a/Documentation/gitworkflows.txt
+++ b/Documentation/gitworkflows.txt
@@ -72,15 +72,15 @@ Graduation
As a given feature goes from experimental to stable, it also
"graduates" between the corresponding branches of the software.
-`git.git` uses the following 'main branches':
+`git.git` uses the following 'integration branches':
* 'maint' tracks the commits that should go into the next "maintenance
release", i.e., update of the last released stable version;
* 'master' tracks the commits that should go into the next release;
-* 'next' is intended as a testing branch for topics not stable enough
- for master yet.
+* 'next' is intended as a testing branch for topics being tested for
+ stability for master.
There is a fourth official branch that is used slightly differently:
@@ -107,7 +107,7 @@ the unstable branch into the stable one. Hence the following:
[caption="Rule: "]
=====================================
Always commit your fixes to the oldest supported branch that require
-them. Then (periodically) merge the main branches upwards into each
+them. Then (periodically) merge the integration branches upwards into each
other.
=====================================
@@ -124,28 +124,32 @@ Topic branches
Any nontrivial feature will require several patches to implement, and
may get extra bugfixes or improvements during its lifetime.
-Committing everything directly on the main branches leads to many
+Committing everything directly on the integration branches leads to many
problems: Bad commits cannot be undone, so they must be reverted one
by one, which creates confusing histories and further error potential
when you forget to revert part of a group of changes. Working in
parallel mixes up the changes, creating further confusion.
-The key concept here is "topic branches". The name is pretty self
-explanatory, with a caveat that comes from the "merge upwards" rule
-above:
+Use of "topic branches" solves these problems. The name is pretty
+self explanatory, with a caveat that comes from the "merge upwards"
+rule above:
.Topic branches
[caption="Rule: "]
=====================================
Make a side branch for every topic (feature, bugfix, ...). Fork it off
-at the oldest main branch that you will eventually want to merge it
+at the oldest integration branch that you will eventually want to merge it
into.
=====================================
Many things can then be done very naturally:
-* To get the feature/bugfix into a main branch, simply merge it. If
- the topic has evolved further in the meantime, merge again.
+* To get the feature/bugfix into an integration branch, simply merge
+ it. If the topic has evolved further in the meantime, merge again.
+ (Note that you do not necessarily have to merge it to the oldest
+ integration branch first. For example, you can first merge a bugfix
+ to 'next', give it some testing time, and merge to 'maint' when you
+ know it is stable.)
* If you find you need new features from the branch 'other' to continue
working on your topic, merge 'other' to 'topic'. (However, do not
@@ -154,35 +158,33 @@ Many things can then be done very naturally:
* If you find you forked off the wrong branch and want to move it
"back in time", use linkgit:git-rebase[1].
-Note that the last two points clash: a topic that has been merged
-elsewhere should not be rebased. See the section on RECOVERING FROM
-UPSTREAM REBASE in linkgit:git-rebase[1].
+Note that the last point clashes with the other two: a topic that has
+been merged elsewhere should not be rebased. See the section on
+RECOVERING FROM UPSTREAM REBASE in linkgit:git-rebase[1].
We should point out that "habitually" (regularly for no real reason)
-merging a main branch into your topics -- and by extension, merging
-anything upstream into anything downstream on a regular basis -- is
-frowned upon:
+merging an integration branch into your topics -- and by extension,
+merging anything upstream into anything downstream on a regular basis
+-- is frowned upon:
.Merge to downstream only at well-defined points
[caption="Rule: "]
=====================================
-Do not merge to downstream except:
-
-* with a good reason: upstream API changes affect your branch; your
- branch no longer merges to upstream cleanly; etc.
-
-* at well-defined points such as when an upstream release has been tagged.
+Do not merge to downstream except with a good reason: upstream API
+changes affect your branch; your branch no longer merges to upstream
+cleanly; etc.
=====================================
-Otherwise, the many resulting small merges will greatly clutter up
-history. Anyone who later investigates the history of a file will
-have to find out whether that merge affected the topic in development.
-An upstream might even inadvertently be merged into a "more stable"
-branch. And so on.
+Otherwise, the topic that was merged to suddenly contains more than a
+single (well-separated) change. The many resulting small merges will
+greatly clutter up history. Anyone who later investigates the history
+of a file will have to find out whether that merge affected the topic
+in development. An upstream might even inadvertently be merged into a
+"more stable" branch. And so on.
-Integration branches
-~~~~~~~~~~~~~~~~~~~~
+Throw-away integration
+~~~~~~~~~~~~~~~~~~~~~~
If you followed the last paragraph, you will now have many small topic
branches, and occasionally wonder how they interact. Perhaps the
@@ -193,7 +195,7 @@ cannot easily be undone.
The solution, of course, is to make a merge that we can undo: merge
into a throw-away branch.
-.Integration branches
+.Throw-away integration branches
[caption="Rule: "]
=====================================
To test the interaction of several topics, merge them into a
@@ -204,7 +206,7 @@ If you make it (very) clear that this branch is going to be deleted
right after the testing, you can even publish this branch, for example
to give the testers a chance to work with it, or other developers a
chance to see if their in-progress work will be compatible. `git.git`
-has such an official integration branch called 'pu'.
+has such an official throw-away integration branch called 'pu'.
DISTRIBUTED WORKFLOWS
@@ -259,7 +261,7 @@ You will still have to tell people by other means, such as mail. (Git
provides the linkgit:request-pull[1] to send preformatted pull
requests to upstream maintainers to simplify this task.)
-If you just want to get the newest copies of the main branches,
+If you just want to get the newest copies of the integration branches,
staying up to date is easy too:
.Push/pull: Staying up to date
@@ -272,8 +274,8 @@ Then simply fork your topic branches from the stable remotes as
explained earlier.
If you are a maintainer and would like to merge other people's topic
-branches to the main branches, they will typically send a request to
-do so by mail. Such a request looks like
+branches to the integration branches, they will typically send a
+request to do so by mail. Such a request looks like
-------------------------------------
Please pull from
--
1.6.0.2.916.g8e7f4
^ permalink raw reply related
* Re: What's cooking in git.git (Oct 2008, #04; Sat, 18)
From: Thomas Rast @ 2008-10-19 15:18 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7viqrpabep.fsf@gitster.siamese.dyndns.org>
[-- Attachment #1: Type: text/plain, Size: 812 bytes --]
Junio C Hamano wrote:
> * tr/workflow-doc (Sat Sep 13 18:11:01 2008 +0200) 2 commits
> + Documentation: Refer to git-rebase(1) to warn against rewriting
> + Documentation: new upstream rebase recovery section in git-rebase
>
> Expecting an update.
Note that the branch name is somewhat misleading; my fault for causing
confusion by grouping these two together with the gitworkflows.txt
RFCs. The two topics are independent.
And needless to say, I also managed to confuse myself. The above two
are already the final version. As far as I can tell, you've also made
two small corrections of your own; much appreciated.
I'll send an updated version of the gitworkflows.txt draft shortly,
which is what I meant in my last mail.
- Thomas
--
Thomas Rast
trast@{inf,student}.ethz.ch
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply
* [PATHv2 8/8] gitweb: make the supported snapshot formats array global
From: Giuseppe Bilotta @ 2008-10-19 14:24 UTC (permalink / raw)
To: git; +Cc: Jakub Narebski, Petr Baudis, Junio C Hamano, Giuseppe Bilotta
In-Reply-To: <1224426270-27755-2-git-send-email-giuseppe.bilotta@gmail.com>
The @snapshot_fmts array, containing the list of the supported snapshot
formats, was recreated locally in three different routines (with the
different name @supported_fmts in one of them).
Its local generation is particularly expensive because two of the
callers, href() and format_snapshot_links(), are often called many times
in a single page.
Simplify code and speed up page generation by making the array global.
Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
---
gitweb/gitweb.perl | 21 ++++++++-------------
1 files changed, 8 insertions(+), 13 deletions(-)
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 5fd5a1f..d1475b7 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -748,6 +748,10 @@ if (defined $searchtext) {
our $git_dir;
$git_dir = "$projectroot/$project" if $project;
+# list of supported snapshot formats
+our @snapshot_fmts = gitweb_check_feature('snapshot');
+@snapshot_fmts = filter_snapshot_fmts(@snapshot_fmts);
+
# dispatch
if (!defined $action) {
if (defined $hash) {
@@ -858,11 +862,7 @@ sub href (%) {
# snapshot_format should always be defined when href()
# is called, but just in case some code forgets, we
# fall back to the default
- if (!$fmt) {
- my @snapshot_fmts = gitweb_check_feature('snapshot');
- @snapshot_fmts = filter_snapshot_fmts(@snapshot_fmts);
- $fmt = $snapshot_fmts[0];
- }
+ $fmt ||= $snapshot_fmts[0];
$href .= $known_snapshot_formats{$fmt}{'suffix'};
delete $params{'snapshot_format'};
}
@@ -1695,8 +1695,6 @@ sub format_diff_line {
# linked. Pass the hash of the tree/commit to snapshot.
sub format_snapshot_links {
my ($hash) = @_;
- my @snapshot_fmts = gitweb_check_feature('snapshot');
- @snapshot_fmts = filter_snapshot_fmts(@snapshot_fmts);
my $num_fmts = @snapshot_fmts;
if ($num_fmts > 1) {
# A parenthesized list of links bearing format names.
@@ -4898,20 +4896,17 @@ sub git_tree {
}
sub git_snapshot {
- my @supported_fmts = gitweb_check_feature('snapshot');
- @supported_fmts = filter_snapshot_fmts(@supported_fmts);
-
my $format = $input_params{'snapshot_format'};
- if (!@supported_fmts) {
+ if (!@snapshot_fmts) {
die_error(403, "Snapshots not allowed");
}
# default to first supported snapshot format
- $format ||= $supported_fmts[0];
+ $format ||= $snapshot_fmts[0];
if ($format !~ m/^[a-z0-9]+$/) {
die_error(400, "Invalid snapshot format parameter");
} elsif (!exists($known_snapshot_formats{$format})) {
die_error(400, "Unknown snapshot format");
- } elsif (!grep($_ eq $format, @supported_fmts)) {
+ } elsif (!grep($_ eq $format, @snapshot_fmts)) {
die_error(403, "Unsupported snapshot format");
}
--
1.5.6.5
^ permalink raw reply related
* [PATHv2 7/8] gitweb: embed snapshot format parameter in PATH_INFO
From: Giuseppe Bilotta @ 2008-10-19 14:24 UTC (permalink / raw)
To: git; +Cc: Jakub Narebski, Petr Baudis, Junio C Hamano, Giuseppe Bilotta
In-Reply-To: <1224426270-27755-1-git-send-email-giuseppe.bilotta@gmail.com>
When PATH_INFO is active, get rid of the sf CGI parameter by embedding
the snapshot format information in the PATH_INFO URL, in the form of an
appropriate extension.
Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
---
gitweb/gitweb.perl | 21 +++++++++++++++++++++
1 files changed, 21 insertions(+), 0 deletions(-)
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index e9e9e60..5fd5a1f 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -795,6 +795,7 @@ sub href (%) {
# - action
# - hash_parent or hash_parent_base:/file_parent
# - hash or hash_base:/file_name
+ # - the snapshot_format as an appropriate suffix
# When the script is the root DirectoryIndex for the domain,
# $href here would be something like http://gitweb.example.com/
@@ -806,6 +807,10 @@ sub href (%) {
$href .= "/".esc_url($params{'project'}) if defined $params{'project'};
delete $params{'project'};
+ # since we destructively absorb parameters, we keep this
+ # boolean that remembers if we're handling a snapshot
+ my $is_snapshot = $params{'action'} eq 'snapshot';
+
# Summary just uses the project path URL, any other action is
# added to the URL
if (defined $params{'action'}) {
@@ -845,6 +850,22 @@ sub href (%) {
$href .= esc_url($params{'hash'});
delete $params{'hash'};
}
+
+ # If the action was a snapshot, we can absorb the
+ # snapshot_format parameter too
+ if ($is_snapshot) {
+ my $fmt = $params{'snapshot_format'};
+ # snapshot_format should always be defined when href()
+ # is called, but just in case some code forgets, we
+ # fall back to the default
+ if (!$fmt) {
+ my @snapshot_fmts = gitweb_check_feature('snapshot');
+ @snapshot_fmts = filter_snapshot_fmts(@snapshot_fmts);
+ $fmt = $snapshot_fmts[0];
+ }
+ $href .= $known_snapshot_formats{$fmt}{'suffix'};
+ delete $params{'snapshot_format'};
+ }
}
# now encode the parameters explicitly
--
1.5.6.5
^ permalink raw reply related
* [PATHv2 6/8] gitweb: retrieve snapshot format from PATH_INFO
From: Giuseppe Bilotta @ 2008-10-19 14:24 UTC (permalink / raw)
To: git; +Cc: Jakub Narebski, Petr Baudis, Junio C Hamano, Giuseppe Bilotta
In-Reply-To: <1224188831-17767-6-git-send-email-giuseppe.bilotta@gmail.com>
We parse requests for $project/snapshot/$head.$sfx as equivalent to
$project/snapshot/$head?sf=$sfx, where $sfx is any of the known
(although not necessarily supported) snapshot formats (or its default
suffix).
The filename for the resulting package preserves the requested
extensions (so asking for a .tgz gives a .tgz, and asking for a .tar.gz
gives a .tar.gz), although for obvious reasons it doesn't preserve the
basename (git/snapshot/next.tgz returns a file names git-next.tgz).
This introduces a potential case for ambiguity if a project has a head
that ends with a snapshot-like suffix (.zip, .tgz, .tar.gz, etc) and the
sf CGI parameter is not present; however, gitweb only produces URLs with
the sf parameter, so this is only a potential issue for hand-coded URLs
for extremely unusual project.
Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
---
I had second thoughts on this. Now we always look for the snapshot extension if
the sf CGI parameter is missing, even if the project has a head that matches
the full pseudo-refname $head.$sfx.
The reason for this is that (1) there is no ambiguity for gitweb-generated
URLs (2) the only URLs that could fail are hand-made URLs for extremely
unusual projects and (3) it allows us to set gitweb up to generate
(unambiguous) URLs without the sf CGI parameter.
This also means that I can add 3 patches to the series, instead of just one:
* patch #6 that parses the new format
* patch #7 that generates the new URLs
* patch #8 for some code refactoring
gitweb/gitweb.perl | 34 ++++++++++++++++++++++++++++++++++
1 files changed, 34 insertions(+), 0 deletions(-)
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 99c8c20..e9e9e60 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -609,6 +609,40 @@ sub evaluate_path_info {
$input_params{'hash_parent'} ||= $parentrefname;
}
}
+
+ # for the snapshot action, we allow URLs in the form
+ # $project/snapshot/$hash.ext
+ # where .ext determines the snapshot and gets removed from the
+ # passed $refname to provide the $hash.
+ #
+ # To be able to tell that $refname includes the format extension, we
+ # require the following two conditions to be satisfied:
+ # - the hash input parameter MUST have been set from the $refname part
+ # of the URL (i.e. they must be equal)
+ # - the snapshot format MUST NOT have been defined already
+ if ($input_params{'action'} eq 'snapshot' && defined $refname &&
+ $refname eq $input_params{'hash'} &&
+ !defined $input_params{'snapshot_format'}) {
+ # We loop over the known snapshot formats, checking for
+ # extensions. Allowed extensions are both the defined suffix
+ # (which includes the initial dot already) and the snapshot
+ # format key itself, with a prepended dot
+ while (my ($fmt, %opt) = each %known_snapshot_formats) {
+ my $hash = $refname;
+ my $sfx;
+ $hash =~ s/(\Q$opt{'suffix'}\E|\Q.$fmt\E)$//;
+ next unless $sfx = $1;
+ # a valid suffix was found, so set the snapshot format
+ # and reset the hash parameter
+ $input_params{'snapshot_format'} = $fmt;
+ $input_params{'hash'} = $hash;
+ # we also set the format suffix to the one requested
+ # in the URL: this way a request for e.g. .tgz returns
+ # a .tgz instead of a .tar.gz
+ $known_snapshot_formats{$fmt}{'suffix'} = $sfx;
+ last;
+ }
+ }
}
evaluate_path_info();
--
1.5.6.5
^ permalink raw reply related
* Re: [PATCH] -C/--chdir command line option
From: Jeff King @ 2008-10-19 14:16 UTC (permalink / raw)
To: Maciej Pasternacki; +Cc: git
In-Reply-To: <86685067-021C-4DC5-A462-AA6834208BDE@pasternacki.net>
On Sun, Oct 19, 2008 at 03:47:04PM +0200, Maciej Pasternacki wrote:
> As for -C being superfluous: --git-dir and --work-tree seem to support
> weird usage patterns (like work tree separate from git-dir), but it seems
Hmm. Yeah, thinking about it more, -C is not really superfluous with
respect to those options. You don't want to say "here is the work-tree,
and here is the git-dir". You want to say "find the work-tree and
git-dir for me using the usual rules, as if I were in this directory."
So you couldn't just say:
git --work-tree=/chdir/path
since that would assume your current directory was the git-dir. You
would need:
git --work-tree=/chdir/path --git-dir=/chdir/path/.git
but then you are overriding any usual lookup rules (e.g., somebody
having set GIT_DIR in the environment).
Though I am not clear from your original description if that is even
what you want. It sounds like you might be doing:
git -C /chdir/path --git-dir=/back/to/where/I/was
in which case I think work-tree _is_ a better fit.
> to me that --work-tree could be just made a synonym of -C, and it would
> behave as expected without creating chicken-and-egg problem that doener on
> #git found (which I don't really understand, but I also can't see what
> --work-tree allows that -C would not -- except creating more fragility).
--work-tree allows you say "I'm _already_ in the git-dir, but please use
this other place for the work-tree". So you can, for example, checkout
files from a bare repository.
>> Also, the envchanged flag should probably be set, as for the git-dir
>> and work-tree options.
>
> OK. I thought it means literally environment change, as in setenv().
It is really used to tell the options parser for aliases that some
options which change the operating environment should not be used in an
alias. I.e., something like:
git config alias.foo "--git-dir=/path/to/whatever log"
isn't allowed, because we have already done some work on setting up the
git-dir at this point. IMHO, this is a limitation of the current
approach to setting up the environment, but fixing it would be
nontrivial.
I'm not 100% sure that doing a chdir should be disallowed in this
instance, but I suspect it would cause problems. I think it is better in
this instance to be conservative and disallow it in aliases.
-Peff
^ permalink raw reply
* Re: [msysGit] Re: Weird filename encoding issue
From: Alexander Gladysh @ 2008-10-19 14:11 UTC (permalink / raw)
To: johannes.sixt; +Cc: msysGit, git
In-Reply-To: <200810181951.53962.johannes.sixt@telecom.at>
On Sat, Oct 18, 2008 at 9:51 PM, Johannes Sixt <johannes.sixt@telecom.at> wrote:
> On Samstag, 18. Oktober 2008, Alexander Gladysh wrote:
>> 1. Git hooks do not work under msysgit.
>
> This is new to me. Why are you saying that? (IOW, please be more precise with
> your description. We can't help you if all you tell us is "Does not work" .)
Err. Sorry. I thought it is a known issue:
http://groups.google.com/group/msysgit/browse_thread/thread/956e555b8d515c66
I've got an impression that msysgit 1.5.6.1.1071.g76fb we use does not
contain this fix.
Of course, I may apply it by hand on each user's machine... Still have
to do it though.
Alexander.
^ permalink raw reply
* Re: [PATCH] -C/--chdir command line option
From: Maciej Pasternacki @ 2008-10-19 13:47 UTC (permalink / raw)
To: git; +Cc: Jeff King
In-Reply-To: <20081019131745.GA8643@coredump.intra.peff.net>
On 2008-10-19, at 15:17, Jeff King wrote:
> On Sat, Oct 18, 2008 at 05:02:27PM -0700, Maciej Pasternacki wrote:
>
>> In my project cl-librarian, which is a layer built upon different
>> version control systems, I need to run git pull, but start it from
>> outside of work tree; however, pull needs to be in work tree (as in
>> getcwd()) in order to update said work tree. --git-dir and
>> --work-tree options don't work; I discussed it on #git yesterday,
>> and it turned out that this issue is nontrivial:
>> [...]
>> the best workaround that occured to me was adding -C/--chdir option
>> to
>> main git binary, like one that Make accepts. This fixed my
>> problem, I
>> paste the resulting patch below:
>
> I'm not completely opposed to -C, as it does match some other tools,
> but it does seem superfluous with --git-dir and --work-tree. Which
> makes
> me feel like we are just papering over a bug instead of actually
> fixing
> it (and to be honest, I always wondered what the point of "make -C"
> was
> in the face of "cd dir && make").
The point of make -C is exactly my usage pattern: invoking make from
external program. I have seen, at least in Lisp (external-program)
and Python (os.spawn, subprocess), libraries to safely and portably
execute external program by giving literal list of arguments (an easy
to use wrapper to fork()+exec(); I don't know if such feature exists
for C). This allows me not to worry about quoting strange characters
in pathnames (think injections, if just making it possible to use "&"
character in directory name is not good enough a reason). The
equivalent of "cd dir && make" would be to use system() or invoke sh -
c; both would require shell-quoting the directory pathname, and would
carry portability issues -- how do I know that shell on target system
is actually called "sh" and it supports "&&"? At least Windows
systems would be problematic.
The -C option allows me to just specify the directory as it is, and
child process, after the fork, will take care of the chdir(). No
quoting, no portability problems, injection-safety included.
As for -C being superfluous: --git-dir and --work-tree seem to support
weird usage patterns (like work tree separate from git-dir), but it
seems to me that --work-tree could be just made a synonym of -C, and
it would behave as expected without creating chicken-and-egg problem
that doener on #git found (which I don't really understand, but I also
can't see what --work-tree allows that -C would not -- except creating
more fragility). I won't push on --work-tree and -C being
functionally synonymous, since I don't know git well enough, it's just
my impression at the moment.
> Please follow the usual list conventions; this stuff should be the
> actual headers of your mail, not in the body of the message. And
> some of
> the justification you gave above should be part of the commit message.
ACK. That was how I understood instructions linked from git.or.cz,
I'll paste message correctly for next version of the patch.
>> + } else if (!strcmp(cmd, "-C") || !strcmp(cmd, "--chdir")) {
>> + chdir((*argv)[1]);
>
> No error detection and reporting? I think I would be quite happy for
> "git -C /some/path clean -dx" to bail out when it saw that it couldn't
> change directory instead of just deleting the contents of wherever I
> happened to be.
Oops. Looks like I'm spoiled by high-level languages that would
automatically catch and display an error. I'll prepare patch v2 today.
> Also, the envchanged flag should probably be set, as for the git-dir
> and
> work-tree options.
OK. I thought it means literally environment change, as in setenv().
Thank you for your comments, off to make v2 patch,
Maciej.
--
-><- Maciej Pasternacki -><- http://www.pasternacki.net/ -><-
^ permalink raw reply
* [JGIT PATCH] Encode/decode index and tree entries using UTF-8
From: Robin Rosenberg @ 2008-10-19 13:29 UTC (permalink / raw)
To: spearce; +Cc: git
Decoding uses the same strategy as for commit messages and other string
entities. Encoding is always done in UTF-8. This is incompatible with
Git for non-unicode unices, but it leads to the expected behavior on
Windows and cross-locale sharing of repositories.
Signed-off-by: Robin Rosenberg <robin.rosnberg@dewire.com>
---
Inpired by the recent thread on the gitml, I decideed to clean up jgit a little. I
know the GitIndex is soon to be obsoleted, but it it still the class that does
the dirty work when committing in Egit and the changes are fairly simple
anyway.
- Unicode paths will work on all platforms that support unicode, i.e. Windows
and any unix using a UTF-8 locale, with one small exception. Accented characters
on OS-X probably do not work well.
- Combined use of unicode on one platform is compatible with non-unicode locales
on other platforms as long as the characters in use are available in the local character
set.
A side note, invalid byte sequences in unix, e.g. ISO-latin-1 encoded file names cannot
work in Java. Such files are inaccessible. Jgit will allow you to rename them in the index,
but that is all.
-- robin
.../src/org/spearce/jgit/lib/GitIndex.java | 27 +++++++++++---------
.../src/org/spearce/jgit/lib/Tree.java | 11 +++----
.../src/org/spearce/jgit/lib/TreeEntry.java | 13 +++------
3 files changed, 25 insertions(+), 26 deletions(-)
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/GitIndex.java b/org.spearce.jgit/src/org/spearce/jgit/lib/GitIndex.java
index 22935ab..3d37033 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/GitIndex.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/GitIndex.java
@@ -63,6 +63,7 @@
import org.spearce.jgit.errors.CorruptObjectException;
import org.spearce.jgit.errors.NotSupportedException;
import org.spearce.jgit.util.FS;
+import org.spearce.jgit.util.RawParseUtils;
/**
* A representation of the Git index.
@@ -178,8 +179,9 @@ public Entry add(File wd, File f) throws IOException {
* @param f
* the file whose path shall be removed.
* @return true if such a path was found (and thus removed)
+ * @throws IOException
*/
- public boolean remove(File wd, File f) {
+ public boolean remove(File wd, File f) throws IOException {
byte[] key = makeKey(wd, f);
return entries.remove(key) != null;
}
@@ -300,11 +302,11 @@ static boolean File_hasExecute() {
return FS.INSTANCE.supportsExecute();
}
- static byte[] makeKey(File wd, File f) {
+ static byte[] makeKey(File wd, File f) throws IOException {
if (!f.getPath().startsWith(wd.getPath()))
throw new Error("Path is not in working dir");
String relName = Repository.stripWorkDir(wd, f);
- return relName.getBytes();
+ return relName.getBytes(Constants.CHARACTER_ENCODING);
}
Boolean filemode;
@@ -376,7 +378,7 @@ Entry(TreeEntry f, int stage)
size = -1;
}
sha1 = f.getId();
- name = f.getFullName().getBytes("UTF-8");
+ name = f.getFullName().getBytes(Constants.CHARACTER_ENCODING);
flags = (short) ((stage << 12) | name.length); // TODO: fix flags
}
@@ -580,7 +582,7 @@ private File getFile(File wd) {
}
public String toString() {
- return new String(name) + "/SHA-1(" + sha1.name() + ")/M:"
+ return getName() + "/SHA-1(" + sha1.name() + ")/M:"
+ new Date(ctime / 1000000L) + "/C:"
+ new Date(mtime / 1000000L) + "/d" + dev + "/i" + ino
+ "/m" + Integer.toString(mode, 8) + "/u" + uid + "/g"
@@ -591,7 +593,7 @@ public String toString() {
* @return path name for this entry
*/
public String getName() {
- return new String(name);
+ return RawParseUtils.decode(Constants.CHARSET, name, 0, name.length);
}
/**
@@ -731,7 +733,7 @@ void readTree(String prefix, Tree t) throws IOException {
readTree(name, (Tree) te);
} else {
Entry e = new Entry(te, 0);
- entries.put(name.getBytes("UTF-8"), e);
+ entries.put(name.getBytes(Constants.CHARACTER_ENCODING), e);
}
}
}
@@ -743,7 +745,7 @@ void readTree(String prefix, Tree t) throws IOException {
* @throws IOException
*/
public Entry addEntry(TreeEntry te) throws IOException {
- byte[] key = te.getFullName().getBytes("UTF-8");
+ byte[] key = te.getFullName().getBytes(Constants.CHARACTER_ENCODING);
Entry e = new Entry(te, 0);
entries.put(key, e);
return e;
@@ -825,7 +827,7 @@ public ObjectId writeTree() throws IOException {
while (trees.size() < newName.length) {
if (!current.existsTree(newName[trees.size() - 1])) {
current = new Tree(current, newName[trees.size() - 1]
- .getBytes());
+ .getBytes(Constants.CHARACTER_ENCODING));
current.getParent().addEntry(current);
trees.push(current);
} else {
@@ -835,7 +837,7 @@ public ObjectId writeTree() throws IOException {
}
}
FileTreeEntry ne = new FileTreeEntry(current, e.sha1,
- newName[newName.length - 1].getBytes(),
+ newName[newName.length - 1].getBytes(Constants.CHARACTER_ENCODING),
(e.mode & FileMode.EXECUTABLE_FILE.getBits()) == FileMode.EXECUTABLE_FILE.getBits());
current.addEntry(ne);
}
@@ -880,7 +882,7 @@ int longestCommonPath(String[] a, String[] b) {
* Small beware: Unaccounted for are unmerged entries. You may want
* to abort if members with stage != 0 are found if you are doing
* any updating operations. All stages will be found after one another
- * here later. Currently only one stage per name is returned.
+ * here later. Currently only one stage per name is returned.
*
* @return The index entries sorted
*/
@@ -896,7 +898,8 @@ int longestCommonPath(String[] a, String[] b) {
* @throws UnsupportedEncodingException
*/
public Entry getEntry(String path) throws UnsupportedEncodingException {
- return (Entry) entries.get(Repository.gitInternalSlash(path.getBytes("ISO-8859-1")));
+ return (Entry) entries.get(Repository.gitInternalSlash(path
+ .getBytes(Constants.CHARACTER_ENCODING)));
}
/**
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Tree.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Tree.java
index 25a9a71..3fd3d30 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Tree.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Tree.java
@@ -44,6 +44,7 @@
import org.spearce.jgit.errors.CorruptObjectException;
import org.spearce.jgit.errors.EntryExistsException;
import org.spearce.jgit.errors.MissingObjectException;
+import org.spearce.jgit.util.RawParseUtils;
/**
* A representation of a Git tree entry. A Tree is a directory in Git.
@@ -281,8 +282,7 @@ public FileTreeEntry addFile(final byte[] s, final int offset)
final byte[] newName = substring(s, offset, slash);
if (p >= 0)
- throw new EntryExistsException(new String(newName,
- Constants.CHARACTER_ENCODING));
+ throw new EntryExistsException(RawParseUtils.decode(Constants.CHARSET, newName, 0, newName.length));
else if (slash < s.length) {
final Tree t = new Tree(this, newName);
insertEntry(p, t);
@@ -332,8 +332,8 @@ public Tree addTree(final byte[] s, final int offset) throws IOException {
final byte[] newName = substring(s, offset, slash);
if (p >= 0)
- throw new EntryExistsException(new String(newName,
- Constants.CHARACTER_ENCODING));
+ throw new EntryExistsException(RawParseUtils.decode(
+ Constants.CHARSET, newName, 0, newName.length));
final Tree t = new Tree(this, newName);
insertEntry(p, t);
@@ -355,8 +355,7 @@ public void addEntry(final TreeEntry e) throws IOException {
e.attachParent(this);
insertEntry(p, e);
} else {
- throw new EntryExistsException(new String(e.getNameUTF8(),
- Constants.CHARACTER_ENCODING));
+ throw new EntryExistsException(e.getName());
}
}
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/TreeEntry.java b/org.spearce.jgit/src/org/spearce/jgit/lib/TreeEntry.java
index 85dda1d..7f58056 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/TreeEntry.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/TreeEntry.java
@@ -39,9 +39,9 @@
package org.spearce.jgit.lib;
import java.io.IOException;
-import java.io.UnsupportedEncodingException;
import org.spearce.jgit.lib.GitIndex.Entry;
+import org.spearce.jgit.util.RawParseUtils;
/**
* This class represents an entry in a tree, like a blob or another tree.
@@ -126,13 +126,10 @@ public Repository getRepository() {
* @return the name of this entry.
*/
public String getName() {
- try {
- return nameUTF8 != null ? new String(nameUTF8,
- Constants.CHARACTER_ENCODING) : null;
- } catch (UnsupportedEncodingException uee) {
- throw new RuntimeException("JVM doesn't support "
- + Constants.CHARACTER_ENCODING, uee);
- }
+ if (nameUTF8 != null)
+ return RawParseUtils.decode(Constants.CHARSET, nameUTF8, 0,
+ nameUTF8.length);
+ return null;
}
/**
--
1.6.0.2.308.gef4a
^ permalink raw reply related
* Re: [PATCH] -C/--chdir command line option
From: Jeff King @ 2008-10-19 13:17 UTC (permalink / raw)
To: Maciej Pasternacki; +Cc: git
In-Reply-To: <20081019000227.GA9423@charybdis.dreamhost.com>
On Sat, Oct 18, 2008 at 05:02:27PM -0700, Maciej Pasternacki wrote:
> In my project cl-librarian, which is a layer built upon different
> version control systems, I need to run git pull, but start it from
> outside of work tree; however, pull needs to be in work tree (as in
> getcwd()) in order to update said work tree. --git-dir and
> --work-tree options don't work; I discussed it on #git yesterday,
> and it turned out that this issue is nontrivial:
> [...]
> the best workaround that occured to me was adding -C/--chdir option to
> main git binary, like one that Make accepts. This fixed my problem, I
> paste the resulting patch below:
I'm not completely opposed to -C, as it does match some other tools,
but it does seem superfluous with --git-dir and --work-tree. Which makes
me feel like we are just papering over a bug instead of actually fixing
it (and to be honest, I always wondered what the point of "make -C" was
in the face of "cd dir && make").
I'm not sure if the actual problem is related to the oft-discussed,
unresolved work-tree startup woes, or is something much simpler to fix.
I'll try to look closer later today.
A few comments on your patch:
> From 4461cd1be99772c93a83bcdfe6e6a86e71abaa35 Mon Sep 17 00:00:00 2001
> From: Maciej Pasternacki <maciej@pasternacki.net>
> Date: Sun, 19 Oct 2008 01:33:49 +0200
> Subject: [PATCH] Add command line option --chdir/-C to allow setting git process work directory.
>
> Signed-off-by: Maciej Pasternacki <maciej@pasternacki.net>
Please follow the usual list conventions; this stuff should be the
actual headers of your mail, not in the body of the message. And some of
the justification you gave above should be part of the commit message.
> + } else if (!strcmp(cmd, "-C") || !strcmp(cmd, "--chdir")) {
> + chdir((*argv)[1]);
No error detection and reporting? I think I would be quite happy for
"git -C /some/path clean -dx" to bail out when it saw that it couldn't
change directory instead of just deleting the contents of wherever I
happened to be.
Also, the envchanged flag should probably be set, as for the git-dir and
work-tree options.
-Peff
^ permalink raw reply
* Re: Detached checkout will clobber branch head when using symlink HEAD
From: Jeff King @ 2008-10-19 13:00 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Matt Draisey, git
In-Reply-To: <7vfxmuhlad.fsf@gitster.siamese.dyndns.org>
On Fri, Oct 17, 2008 at 04:08:42PM -0700, Junio C Hamano wrote:
> I do not think that is a correct approach.
>
> The offending callchain is:
>
> update_ref(..., "HEAD", REF_NODEREF, ...);
> -> lock_any_ref_for_update("HEAD", ..., REF_NODEREF);
> -> lock_ref_sha1_basic("HEAD", ..., REF_NODEREF, ...);
> . calls resolve_ref() to read HEAD to arrive at
> refs/heads/master
> . however, it notices REF_NODEREF and adjusts the ref to be updated
> back to "HEAD";
> -> hold_lock_file_for_update(..., "HEAD", 1);
> -> lock_file(..., "HEAD");
> . resolves symlink "HEAD" to "refs/heads/master", and
> locks it! This creates "refs/heads/master.lock", that is
> then renamed to "refs/heads/master" when unlocked.
>
> In other words, the breakage is in lock_file() and not in resolve_ref().
> The latter gives the same output to the caller whether the HEAD is
> symbolic link or textual symref -- at least it should.
To be fair, my patch fixed the problem in lock_ref_sha1_basic, not
resolve_ref. It merely asked resolve_ref to annotate the resolution to
show whether a symlink was found, since it already had that information.
But if I am reading your patch right, you are actually enabling detached
HEAD in this instance, which is much better. Unfortunately, I had quite
a few conflicts in applying your patches on top of master (with or
without the patch from "checkout --track -b broken"), and when I thought
I had fixed up the result, the test actually still failed.
So I will take your word that it actually works, and that I screwed up
resolving the conflicts.
-Peff
PS If you are rebasing or resolving anyway, as I suspect you will have
to, there is a typo in the test: s/detch/detach/
^ permalink raw reply
* Re: [PATCH v2] Fix testcase failure when extended attributes are in use
From: Deskin Miller @ 2008-10-19 12:24 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, heikki.orsila
In-Reply-To: <7vbpxig4fb.fsf@gitster.siamese.dyndns.org>
On Fri, Oct 17, 2008 at 04:58:16PM -0700, Junio C Hamano wrote:
> With 8ed0a74 (t1301-shared-repo.sh: don't let a default ACL interfere with
> the test, 2008-10-16) applied is this still needed, or can I drop it from
> my review box?
Apologies for a tardy response, was out of town and away from keyboard for a
day.
This patch is still needed, as my and Matt's patch are solving two different
issues with t1301. As he pointed out in the thread regarding his patch, the
issue was that the testcase was intended to specifically test Git's interaction
with permissions set via the umask, but a default ACL on the 'trash directory'
could interfere with this, since they'd override the umask settings. Remove
the ACL, no problem.
My patch, on the other hand, is to deal with 'ls' output in case a file has
certain filesystem extended attributes. These could be e.g. POSIX ACLs, or a
SELinux security context, or perhaps others. If such an extended attribute is
present, 'ls -l' will print permissions with a '+' appended, e.g.
-rw-r--r--+
Instead of
-rw-r--r--
However, t1301 reads permissions output by ls for several tests, and compares
them to string representations such as that above. Without removing the '+',
if present, the strings will not match. Furthermore, since this occurs for
other filesystem extended attributes, and not just ACLs, it is not possible to
simply strip all extended attributes from the file in question (with SELinux,
the kernel won't let you remove a file's security context anyway).
For what it's worth, I've experienced this failure on my Ubuntu 8.04 laptop
with SELinux permissive mode, so it's possible ls behaves slightly differently
on other systems; I've not been able to determine this one way or another.
However, I see no harm in accounting for this situation in the general case,
since the typical output of ls on other systems will not be affected nor
modified with this patch.
Hope that helps,
Deskin Miller
^ permalink raw reply
* [PATCH 6/6] gitweb: retrieve snapshot format from PATH_INFO
From: Giuseppe Bilotta @ 2008-10-19 12:11 UTC (permalink / raw)
To: git; +Cc: Jakub Narebski, Petr Baudis, Junio C Hamano, Giuseppe Bilotta
In-Reply-To: <1224188831-17767-6-git-send-email-giuseppe.bilotta@gmail.com>
We parse requests for $project/snapshot/$head.$sfx as equivalent to
$project/snapshot/$head?sf=$sfx, where $sfx is any of the known
(although not necessarily supported) snapshot formats (or its default
suffix).
The filename for the resulting package preserves the requested
extensions (so asking for a .tgz gives a .tgz, and asking for a .tar.gz
gives a .tar.gz), although for obvious reasons it doesn't preserve the
basename (git/snapshot/next.tgz returns a file names git-next.tgz).
Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
---
Ok, I lied, there's a 6th patch ready. Its purpose is to allow embedding of
the snapshot format parameter in the URL, in the form of an extension
appended to the refname.
I have not prepared the corresponding URL generation code yet, because of
potential ambiguity that might arise: even though at URL generation time
the project does not have a head named $head.$sfx, it is possible (although
extremely unlikely) that such head is created later on, and the PATH_INFO
generation code cannot therefore guarantee the permalink nature of the
embedded snapshot format URL.
gitweb/gitweb.perl | 35 +++++++++++++++++++++++++++++++++++
1 files changed, 35 insertions(+), 0 deletions(-)
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 99c8c20..7ffd10b 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -609,6 +609,41 @@ sub evaluate_path_info {
$input_params{'hash_parent'} ||= $parentrefname;
}
}
+
+ # for the snapshot action, we allow URLs in the form
+ # $project/snapshot/$hash.ext
+ # where .ext determines the snapshot and gets removed from the
+ # passed $refname to provide the $hash.
+ #
+ # To be able to tell that $refname includes the format extension, we
+ # require some conditions to be satisfied:
+ # - the hash input parameter MUST have been set from the $refname part
+ # of the URL (i.e. they must be equal)
+ # - the snapshot format MUST NOT have been defined already
+ # - the $refname itself MUST NOT be a valid refname
+ if ($input_params{'action'} eq 'snapshot' && defined $refname &&
+ $refname eq $input_params{'hash'} &&
+ !defined $input_params{'snapshot_format'} &&
+ !parse_commit($refname)) {
+ # We loop over the known snapshot formats, checking for
+ # extensions. Allowed extensions are both the defined suffix
+ # (which includes the initial dot already) and the snapshot
+ # format key itself, with a prepended dot
+ while (my ($fmt, %opt) = each %known_snapshot_formats) {
+ my $hash = $refname;
+ my $sfx;
+ $hash =~ s/(\Q$opt{'suffix'}\E|\Q.$fmt\E)$//;
+ next unless $sfx = $1;
+ # a valid suffix was found, so set the snapshot format
+ # and reset the hash parameter
+ $input_params{'snapshot_format'} = $fmt;
+ $input_params{'hash'} = $hash;
+ # we also set the format suffix to the one requested
+ # in the URL: this way a request for e.g. .tgz returns
+ # a .tgz instead of a .tar.gz
+ $known_snapshot_formats{$fmt}{'suffix'} = $sfx;
+ }
+ }
}
evaluate_path_info();
--
1.5.6.5
^ permalink raw reply related
* Re: What's cooking in git.git (Oct 2008, #04; Sat, 18)
From: Jeff King @ 2008-10-19 12:01 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7viqrpabep.fsf@gitster.siamese.dyndns.org>
On Sat, Oct 18, 2008 at 01:36:14PM -0700, Junio C Hamano wrote:
> ----------------------------------------------------------------
> [Actively Cooking]
[...]
> * jk/diff-convfilter (Sun Oct 5 17:43:45 2008 -0400) 4 commits
> + diff: add filter for converting binary to text
> + diff: introduce diff.<driver>.binary
> + diff: unify external diff and funcname parsing code
> + t4012: use test_cmp instead of cmp
>
> A general cleanup on how diff drivers are implemented. Its still
> missing documentation updates and tests but doesn't break anything
> current as far as I can tell.
Hmm, I was planning on re-rolling this before it hit next to deal with
the issues brought up about the binary option, but I guess it is too
late now (yes, I was being slow about it...). I think I can salvage it
with some patches on top, though.
-Peff
^ 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