* [PATCH 1/7] sha1_file: keep track of where an SHA-1 object comes from
From: Nguyễn Thái Ngọc Duy @ 2013-01-24 8:42 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Jens Lehmann,
Nguyễn Thái Ngọc Duy
We currently know if an object is loose or packed. We do not know if
it's from the repo's object database, or via alternates
mechanism. With this patch, sha1_object_info_extended() can tell if an
object comes from alternates source (and which one).
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
How about this way instead: we keep track of where objects come from
so we can verify object source when we create or update something
that contains SHA-1.
1/7 and 2/7 prepare for tracking object source. The rest verifies
that new commits, trees, tags, indexes, refs or reflogs do not refer
to an external source.
This adds some cost when add_submodule_odb() is used. I did not
measure, but I guess the added cost is much smaller compared to
forking, especially on Windows. No breakages detected by the test
suite, which is really good (or my code is really broken).
builtin/index-pack.c | 2 +-
cache.h | 4 +++-
fast-import.c | 2 +-
sha1_file.c | 66 ++++++++++++++++++++++++++++++++++++----------------
4 files changed, 51 insertions(+), 23 deletions(-)
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 43d364b..a7de3f8 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -1393,7 +1393,7 @@ static void read_v2_anomalous_offsets(struct packed_git *p,
static void read_idx_option(struct pack_idx_option *opts, const char *pack_name)
{
- struct packed_git *p = add_packed_git(pack_name, strlen(pack_name), 1);
+ struct packed_git *p = add_packed_git(pack_name, strlen(pack_name), 1, NULL);
if (!p)
die(_("Cannot open existing pack file '%s'"), pack_name);
diff --git a/cache.h b/cache.h
index c257953..92854ab 100644
--- a/cache.h
+++ b/cache.h
@@ -978,6 +978,7 @@ struct pack_window {
extern struct packed_git {
struct packed_git *next;
struct pack_window *windows;
+ struct alternate_object_database *alt;
off_t pack_size;
const void *index_data;
size_t index_size;
@@ -1066,7 +1067,7 @@ extern void close_pack_windows(struct packed_git *);
extern void unuse_pack(struct pack_window **);
extern void free_pack_by_name(const char *);
extern void clear_delta_base_cache(void);
-extern struct packed_git *add_packed_git(const char *, int, int);
+extern struct packed_git *add_packed_git(const char *, int, int, struct alternate_object_database *);
extern const unsigned char *nth_packed_object_sha1(struct packed_git *, uint32_t);
extern off_t nth_packed_object_offset(const struct packed_git *, uint32_t);
extern off_t find_pack_entry_one(const unsigned char *, struct packed_git *);
@@ -1102,6 +1103,7 @@ struct object_info {
unsigned int is_delta;
} packed;
} u;
+ struct alternate_object_database *alt;
};
extern int sha1_object_info_extended(const unsigned char *, struct object_info *);
diff --git a/fast-import.c b/fast-import.c
index c2a814e..4bf732e 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -964,7 +964,7 @@ static void end_packfile(void)
idx_name = keep_pack(create_index());
/* Register the packfile with core git's machinery. */
- new_p = add_packed_git(idx_name, strlen(idx_name), 1);
+ new_p = add_packed_git(idx_name, strlen(idx_name), 1, NULL);
if (!new_p)
die("core git rejected index %s", idx_name);
all_packs[pack_id] = new_p;
diff --git a/sha1_file.c b/sha1_file.c
index 40b2329..afc7355 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -933,7 +933,8 @@ static void try_to_free_pack_memory(size_t size)
release_pack_memory(size, -1);
}
-struct packed_git *add_packed_git(const char *path, int path_len, int local)
+struct packed_git *add_packed_git(const char *path, int path_len, int local,
+ struct alternate_object_database *alt)
{
static int have_set_try_to_free_routine;
struct stat st;
@@ -973,6 +974,7 @@ struct packed_git *add_packed_git(const char *path, int path_len, int local)
p->mtime = st.st_mtime;
if (path_len < 40 || get_sha1_hex(path + path_len - 40, p->sha1))
hashclr(p->sha1);
+ p->alt = alt;
return p;
}
@@ -1000,7 +1002,8 @@ void install_packed_git(struct packed_git *pack)
packed_git = pack;
}
-static void prepare_packed_git_one(char *objdir, int local)
+static void prepare_packed_git_one(char *objdir, int local,
+ struct alternate_object_database *alt)
{
/* Ensure that this buffer is large enough so that we can
append "/pack/" without clobbering the stack even if
@@ -1041,7 +1044,7 @@ static void prepare_packed_git_one(char *objdir, int local)
/* See if it really is a valid .idx file with corresponding
* .pack file that we can map.
*/
- p = add_packed_git(path, len + namelen, local);
+ p = add_packed_git(path, len + namelen, local, alt);
if (!p)
continue;
install_packed_git(p);
@@ -1110,11 +1113,11 @@ void prepare_packed_git(void)
if (prepare_packed_git_run_once)
return;
- prepare_packed_git_one(get_object_directory(), 1);
+ prepare_packed_git_one(get_object_directory(), 1, NULL);
prepare_alt_odb();
for (alt = alt_odb_list; alt; alt = alt->next) {
alt->name[-1] = 0;
- prepare_packed_git_one(alt->base, 0);
+ prepare_packed_git_one(alt->base, 0, alt);
alt->name[-1] = '/';
}
rearrange_packed_git();
@@ -1215,15 +1218,19 @@ static int git_open_noatime(const char *name)
}
}
-static int open_sha1_file(const unsigned char *sha1)
+static int open_sha1_file(const unsigned char *sha1,
+ struct alternate_object_database **p_alt)
{
int fd;
char *name = sha1_file_name(sha1);
struct alternate_object_database *alt;
fd = git_open_noatime(name);
- if (fd >= 0)
+ if (fd >= 0) {
+ if (p_alt)
+ *p_alt = NULL;
return fd;
+ }
prepare_alt_odb();
errno = ENOENT;
@@ -1231,18 +1238,23 @@ static int open_sha1_file(const unsigned char *sha1)
name = alt->name;
fill_sha1_path(name, sha1);
fd = git_open_noatime(alt->base);
- if (fd >= 0)
+ if (fd >= 0) {
+ if (p_alt)
+ *p_alt = alt;
return fd;
+ }
}
return -1;
}
-void *map_sha1_file(const unsigned char *sha1, unsigned long *size)
+static void *map_sha1_file_extended(const unsigned char *sha1,
+ unsigned long *size,
+ struct alternate_object_database **p_alt)
{
void *map;
int fd;
- fd = open_sha1_file(sha1);
+ fd = open_sha1_file(sha1, p_alt);
map = NULL;
if (fd >= 0) {
struct stat st;
@@ -1261,6 +1273,11 @@ void *map_sha1_file(const unsigned char *sha1, unsigned long *size)
return map;
}
+void *map_sha1_file(const unsigned char *sha1, unsigned long *size)
+{
+ return map_sha1_file_extended(sha1, size, NULL);
+}
+
/*
* There used to be a second loose object header format which
* was meant to mimic the in-pack format, allowing for direct
@@ -2096,7 +2113,9 @@ static int fill_pack_entry(const unsigned char *sha1,
return 1;
}
-static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
+static int find_pack_entry(const unsigned char *sha1,
+ struct pack_entry *e,
+ struct alternate_object_database **p_alt)
{
struct packed_git *p;
@@ -2104,14 +2123,19 @@ static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
if (!packed_git)
return 0;
- if (last_found_pack && fill_pack_entry(sha1, e, last_found_pack))
+ if (last_found_pack && fill_pack_entry(sha1, e, last_found_pack)) {
+ if (p_alt)
+ *p_alt = last_found_pack->alt;
return 1;
+ }
for (p = packed_git; p; p = p->next) {
if (p == last_found_pack || !fill_pack_entry(sha1, e, p))
continue;
last_found_pack = p;
+ if (p_alt)
+ *p_alt = p->alt;
return 1;
}
return 0;
@@ -2130,7 +2154,9 @@ struct packed_git *find_sha1_pack(const unsigned char *sha1,
}
-static int sha1_loose_object_info(const unsigned char *sha1, unsigned long *sizep)
+static int sha1_loose_object_info(const unsigned char *sha1,
+ unsigned long *sizep,
+ struct alternate_object_database **p_alt)
{
int status;
unsigned long mapsize, size;
@@ -2138,7 +2164,7 @@ static int sha1_loose_object_info(const unsigned char *sha1, unsigned long *size
git_zstream stream;
char hdr[32];
- map = map_sha1_file(sha1, &mapsize);
+ map = map_sha1_file_extended(sha1, &mapsize, p_alt);
if (!map)
return error("unable to find %s", sha1_to_hex(sha1));
if (unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr)) < 0)
@@ -2168,9 +2194,9 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi)
return co->type;
}
- if (!find_pack_entry(sha1, &e)) {
+ if (!find_pack_entry(sha1, &e, &oi->alt)) {
/* Most likely it's a loose object. */
- status = sha1_loose_object_info(sha1, oi->sizep);
+ status = sha1_loose_object_info(sha1, oi->sizep, &oi->alt);
if (status >= 0) {
oi->whence = OI_LOOSE;
return status;
@@ -2178,7 +2204,7 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi)
/* Not a loose object; someone else may have just packed it. */
reprepare_packed_git();
- if (!find_pack_entry(sha1, &e))
+ if (!find_pack_entry(sha1, &e, &oi->alt))
return status;
}
@@ -2213,7 +2239,7 @@ static void *read_packed_sha1(const unsigned char *sha1,
struct pack_entry e;
void *data;
- if (!find_pack_entry(sha1, &e))
+ if (!find_pack_entry(sha1, &e, NULL))
return NULL;
data = cache_or_unpack_entry(e.p, e.offset, size, type, 1);
if (!data) {
@@ -2618,14 +2644,14 @@ int has_pack_index(const unsigned char *sha1)
int has_sha1_pack(const unsigned char *sha1)
{
struct pack_entry e;
- return find_pack_entry(sha1, &e);
+ return find_pack_entry(sha1, &e, NULL);
}
int has_sha1_file(const unsigned char *sha1)
{
struct pack_entry e;
- if (find_pack_entry(sha1, &e))
+ if (find_pack_entry(sha1, &e, NULL))
return 1;
return has_loose_object(sha1);
}
--
1.8.0.rc3.18.g0d9b108
^ permalink raw reply related
* [PATCH 2/7] sha1_file: separate alt object db from own repos and submodules's
From: Nguyễn Thái Ngọc Duy @ 2013-01-24 8:42 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Jens Lehmann,
Nguyễn Thái Ngọc Duy
In-Reply-To: <1359016940-18849-1-git-send-email-pclouds@gmail.com>
A submodule's object database may be imported to in-core object pool
for a quick peek without paying the price of running a separate git
command. These databases are marked in for stricter checks later to
avoid accidentially refering to a submodule's SHA-1 from main repo
(except in gitlinks).
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
cache.h | 4 +++-
environment.c | 2 ++
sha1_file.c | 38 +++++++++++++++++++++++++++++---------
submodule.c | 2 +-
4 files changed, 35 insertions(+), 11 deletions(-)
diff --git a/cache.h b/cache.h
index 92854ab..b8d5826 100644
--- a/cache.h
+++ b/cache.h
@@ -561,6 +561,7 @@ extern int fsync_object_files;
extern int core_preload_index;
extern int core_apply_sparse_checkout;
extern int precomposed_unicode;
+extern int object_database_contaminated;
enum branch_track {
BRANCH_TRACK_UNSPECIFIED = -1,
@@ -957,11 +958,12 @@ extern void remove_scheduled_dirs(void);
extern struct alternate_object_database {
struct alternate_object_database *next;
+ int external;
char *name;
char base[FLEX_ARRAY]; /* more */
} *alt_odb_list;
extern void prepare_alt_odb(void);
-extern void read_info_alternates(const char * relative_base, int depth);
+extern void read_external_info_alternates(const char * relative_base, int depth);
extern void add_to_alternates_file(const char *reference);
typedef int alt_odb_fn(struct alternate_object_database *, void *);
extern void foreach_alt_odb(alt_odb_fn, void*);
diff --git a/environment.c b/environment.c
index 85edd7f..3c90d95 100644
--- a/environment.c
+++ b/environment.c
@@ -65,6 +65,8 @@ unsigned long pack_size_limit_cfg;
/* Parallel index stat data preload? */
int core_preload_index = 0;
+int object_database_contaminated;
+
/* This is set by setup_git_dir_gently() and/or git_default_config() */
char *git_work_tree_cfg;
static char *work_tree;
diff --git a/sha1_file.c b/sha1_file.c
index afc7355..af71122 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -58,6 +58,9 @@ static struct cached_object empty_tree = {
static struct packed_git *last_found_pack;
+static void read_info_alternates(const char * relative_base,
+ int depth, int external);
+
static struct cached_object *find_cached_object(const unsigned char *sha1)
{
int i;
@@ -247,7 +250,10 @@ static int git_open_noatime(const char *name);
* SHA1, an extra slash for the first level indirection, and the
* terminating NUL.
*/
-static int link_alt_odb_entry(const char *entry, const char *relative_base, int depth)
+static int link_alt_odb_entry(const char *entry,
+ const char *relative_base,
+ int depth,
+ int external)
{
const char *objdir = get_object_directory();
struct alternate_object_database *ent;
@@ -277,6 +283,7 @@ static int link_alt_odb_entry(const char *entry, const char *relative_base, int
memcpy(ent->base, pathbuf.buf, pfxlen);
strbuf_release(&pathbuf);
+ ent->external = external;
ent->name = ent->base + pfxlen + 1;
ent->base[pfxlen + 3] = '/';
ent->base[pfxlen] = ent->base[entlen-1] = 0;
@@ -310,15 +317,19 @@ static int link_alt_odb_entry(const char *entry, const char *relative_base, int
ent->next = NULL;
/* recursively add alternates */
- read_info_alternates(ent->base, depth + 1);
+ read_info_alternates(ent->base, depth + 1, 0);
ent->base[pfxlen] = '/';
+ if (external)
+ object_database_contaminated = 1;
+
return 0;
}
static void link_alt_odb_entries(const char *alt, int len, int sep,
- const char *relative_base, int depth)
+ const char *relative_base,
+ int depth, int external)
{
struct string_list entries = STRING_LIST_INIT_NODUP;
char *alt_copy;
@@ -340,14 +351,16 @@ static void link_alt_odb_entries(const char *alt, int len, int sep,
error("%s: ignoring relative alternate object store %s",
relative_base, entry);
} else {
- link_alt_odb_entry(entry, relative_base, depth);
+ link_alt_odb_entry(entry, relative_base,
+ depth, external);
}
}
string_list_clear(&entries, 0);
free(alt_copy);
}
-void read_info_alternates(const char * relative_base, int depth)
+static void read_info_alternates(const char * relative_base,
+ int depth, int external)
{
char *map;
size_t mapsz;
@@ -371,11 +384,18 @@ void read_info_alternates(const char * relative_base, int depth)
map = xmmap(NULL, mapsz, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
- link_alt_odb_entries(map, mapsz, '\n', relative_base, depth);
+ link_alt_odb_entries(map, mapsz, '\n', relative_base,
+ depth, external);
munmap(map, mapsz);
}
+void read_external_info_alternates(const char *relative_base,
+ int depth)
+{
+ read_info_alternates(relative_base, depth, 1);
+}
+
void add_to_alternates_file(const char *reference)
{
struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
@@ -385,7 +405,7 @@ void add_to_alternates_file(const char *reference)
if (commit_lock_file(lock))
die("could not close alternates file");
if (alt_odb_tail)
- link_alt_odb_entries(alt, strlen(alt), '\n', NULL, 0);
+ link_alt_odb_entries(alt, strlen(alt), '\n', NULL, 0, 0);
}
void foreach_alt_odb(alt_odb_fn fn, void *cb)
@@ -409,9 +429,9 @@ void prepare_alt_odb(void)
if (!alt) alt = "";
alt_odb_tail = &alt_odb_list;
- link_alt_odb_entries(alt, strlen(alt), PATH_SEP, NULL, 0);
+ link_alt_odb_entries(alt, strlen(alt), PATH_SEP, NULL, 0, 0);
- read_info_alternates(get_object_directory(), 0);
+ read_info_alternates(get_object_directory(), 0, 0);
}
static int has_loose_object_local(const unsigned char *sha1)
diff --git a/submodule.c b/submodule.c
index 2f55436..8e4e2ec 100644
--- a/submodule.c
+++ b/submodule.c
@@ -65,7 +65,7 @@ static int add_submodule_odb(const char *path)
alt_odb_list = alt_odb;
/* add possible alternates from the submodule */
- read_info_alternates(objects_directory.buf, 0);
+ read_external_info_alternates(objects_directory.buf, 0);
prepare_alt_odb();
done:
strbuf_release(&objects_directory);
--
1.8.0.rc3.18.g0d9b108
^ permalink raw reply related
* [PATCH 3/7] sha1_file: refuse to write commits referring to external objects
From: Nguyễn Thái Ngọc Duy @ 2013-01-24 8:42 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Jens Lehmann,
Nguyễn Thái Ngọc Duy
In-Reply-To: <1359016940-18849-1-git-send-email-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
sha1_file.c | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/sha1_file.c b/sha1_file.c
index af71122..5948dcb 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -2615,12 +2615,46 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
return move_temp_to_file(tmp_file, filename);
}
+static void check_sha1_file_for_external_source(const char *buf,
+ unsigned long len,
+ const char *type)
+{
+ struct object_info oi;
+ unsigned char sha1[20];
+
+ /*
+ * It is assumed that the object is well formatted. Otherwise
+ * die() is waiting..
+ */
+ if (!strcmp(type, "commit")) {
+ const char *tail = buf + len;
+ if (get_sha1_hex(buf + 5, sha1) < 0 ||
+ sha1_object_info_extended(sha1, &oi) != OBJ_TREE ||
+ (oi.alt && oi.alt->external))
+ die("cannot create a commit with external tree %s",
+ sha1_to_hex(sha1));
+ buf += 46; /* "tree " + "hex sha1" + "\n" */
+
+ while (buf + 48 < tail && !memcmp(buf, "parent ", 7)) {
+ if (get_sha1_hex(buf + 7, sha1) < 0 ||
+ sha1_object_info_extended(sha1, &oi) != OBJ_COMMIT ||
+ (oi.alt && oi.alt->external))
+ die("cannot create a commit with external parent %s",
+ sha1_to_hex(sha1));
+ buf += 48; /* "parent " + hex sha1 + "\n" */
+ }
+ }
+}
+
int write_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *returnsha1)
{
unsigned char sha1[20];
char hdr[32];
int hdrlen;
+ if (object_database_contaminated)
+ check_sha1_file_for_external_source(buf, len, type);
+
/* Normally if we have it in the pack then we do not bother writing
* it out into .git/objects/??/?{38} file.
*/
--
1.8.0.rc3.18.g0d9b108
^ permalink raw reply related
* [PATCH 4/7] sha1_file: refuse to write trees referring to external objects
From: Nguyễn Thái Ngọc Duy @ 2013-01-24 8:42 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Jens Lehmann,
Nguyễn Thái Ngọc Duy
In-Reply-To: <1359016940-18849-1-git-send-email-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
sha1_file.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/sha1_file.c b/sha1_file.c
index 5948dcb..ec3a040 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -2643,6 +2643,29 @@ static void check_sha1_file_for_external_source(const char *buf,
sha1_to_hex(sha1));
buf += 48; /* "parent " + hex sha1 + "\n" */
}
+ } else if (!strcmp(type, "tree")) {
+ struct tree_desc desc;
+ struct name_entry entry;
+
+ init_tree_desc(&desc, buf, len);
+ while (tree_entry(&desc, &entry))
+ switch (entry.mode) {
+ case S_IFGITLINK:
+ /* we already know we probably don't have this SHA-1 */
+ break;
+ case S_IFDIR:
+ if (sha1_object_info_extended(entry.sha1, &oi) != OBJ_TREE ||
+ (oi.alt && oi.alt->external))
+ die("cannot create a tree with external tree %s",
+ sha1_to_hex(entry.sha1));
+ break;
+ default:
+ if (sha1_object_info_extended(entry.sha1, &oi) != OBJ_BLOB ||
+ (oi.alt && oi.alt->external))
+ die("cannot create a tree with external blob %s",
+ sha1_to_hex(entry.sha1));
+ break;
+ }
}
}
--
1.8.0.rc3.18.g0d9b108
^ permalink raw reply related
* [PATCH 5/7] sha1_file: refuse to write tags referring to external objects
From: Nguyễn Thái Ngọc Duy @ 2013-01-24 8:42 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Jens Lehmann,
Nguyễn Thái Ngọc Duy
In-Reply-To: <1359016940-18849-1-git-send-email-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
sha1_file.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/sha1_file.c b/sha1_file.c
index ec3a040..01681e5 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -2666,6 +2666,12 @@ static void check_sha1_file_for_external_source(const char *buf,
sha1_to_hex(entry.sha1));
break;
}
+ } else if (!strcmp(type, "tag")) {
+ if (get_sha1_hex(buf + 7, sha1) < 0 ||
+ sha1_object_info_extended(sha1, &oi) != OBJ_TREE ||
+ (oi.alt && oi.alt->external))
+ die("cannot create a tag with external tree %s",
+ sha1_to_hex(sha1));
}
}
--
1.8.0.rc3.18.g0d9b108
^ permalink raw reply related
* [PATCH 6/7] read-cache: refuse to create index referring to external objects
From: Nguyễn Thái Ngọc Duy @ 2013-01-24 8:42 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Jens Lehmann,
Nguyễn Thái Ngọc Duy
In-Reply-To: <1359016940-18849-1-git-send-email-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
read-cache.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/read-cache.c b/read-cache.c
index fda78bc..4579215 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -1720,6 +1720,26 @@ static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce,
ce->name + common, ce_namelen(ce) - common);
}
+ if (object_database_contaminated) {
+ struct object_info oi;
+ switch (ce->ce_mode) {
+ case S_IFGITLINK:
+ break;
+ case S_IFDIR:
+ if (sha1_object_info_extended(ce->sha1, &oi) != OBJ_TREE ||
+ (oi.alt && oi.alt->external))
+ die("cannot create index referring to an external tree %s",
+ sha1_to_hex(ce->sha1));
+ break;
+ default:
+ if (sha1_object_info_extended(ce->sha1, &oi) != OBJ_BLOB ||
+ (oi.alt && oi.alt->external))
+ die("cannot create index referring to an external blob %s",
+ sha1_to_hex(ce->sha1));
+ break;
+ }
+ }
+
result = ce_write(c, fd, ondisk, size);
free(ondisk);
return result;
--
1.8.0.rc3.18.g0d9b108
^ permalink raw reply related
* [PATCH 7/7] refs: do not update ref(log) referring to external objects
From: Nguyễn Thái Ngọc Duy @ 2013-01-24 8:42 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Jens Lehmann,
Nguyễn Thái Ngọc Duy
In-Reply-To: <1359016940-18849-1-git-send-email-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
refs.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/refs.c b/refs.c
index 541fec2..86003af 100644
--- a/refs.c
+++ b/refs.c
@@ -2014,6 +2014,18 @@ static int log_ref_write(const char *refname, const unsigned char *old_sha1,
char *logrec;
const char *committer;
+ if (object_database_contaminated) {
+ struct object_info oi;
+ if (sha1_object_info_extended(old_sha1, &oi) == -1 ||
+ (oi.alt && oi.alt->external))
+ return error("cannot update reflog pointing to an external SHA-1 %s",
+ sha1_to_hex(old_sha1));
+ if (sha1_object_info_extended(new_sha1, &oi) == -1 ||
+ (oi.alt && oi.alt->external))
+ return error("cannot update reflog pointing to an external SHA-1 %s",
+ sha1_to_hex(new_sha1));
+ }
+
if (log_all_ref_updates < 0)
log_all_ref_updates = !is_bare_repository();
@@ -2054,6 +2066,18 @@ int write_ref_sha1(struct ref_lock *lock,
if (!lock)
return -1;
+
+ if (object_database_contaminated) {
+ struct object_info oi;
+ if (sha1_object_info_extended(sha1, &oi) == -1 ||
+ (oi.alt && oi.alt->external)) {
+ error("cannot update ref pointing to an external SHA-1 %s",
+ sha1_to_hex(sha1));
+ unlock_ref(lock);
+ return -1;
+ }
+ }
+
if (!lock->force_write && !hashcmp(lock->old_sha1, sha1)) {
unlock_ref(lock);
return 0;
--
1.8.0.rc3.18.g0d9b108
^ permalink raw reply related
* [PATCH v4 0/4] Reroll patches against v1.8.1.1
From: Alexey Shumkin @ 2013-01-24 9:10 UTC (permalink / raw)
To: git; +Cc: Alexey Shumkin, Junio C Hamano
In-Reply-To: <20110921004602.3d59bed4@zappedws>
Woooof!
Reroll my patches again after 1.5 years ;)
They must be applied against v1.8.1.1
Sorry for my laziness ;)
Alexey Shumkin (4):
t6006 (rev-list-format): don't hardcode SHA-1 in expected outputs
t7102 (reset): refactoring: don't hardcode SHA-1 in expected outputs
pretty: Add failing tests: user format ignores i18n.logOutputEncoding
setting
pretty: user format ignores i18n.logOutputEncoding setting
builtin/reset.c | 8 +-
builtin/rev-list.c | 1 +
builtin/shortlog.c | 1 +
log-tree.c | 1 +
submodule.c | 3 +
t/t4041-diff-submodule-option.sh | 23 +++--
t/t4205-log-pretty-formats.sh | 37 ++++++--
t/t6006-rev-list-format.sh | 200 +++++++++++++++++++++++----------------
t/t7102-reset.sh | 71 +++++++++-----
9 files changed, 224 insertions(+), 121 deletions(-)
--
1.8.1.1.10.g9255f3f
^ permalink raw reply
* [PATCH v4 1/4] t6006 (rev-list-format): don't hardcode SHA-1 in expected outputs
From: Alexey Shumkin @ 2013-01-24 9:10 UTC (permalink / raw)
To: git; +Cc: Alexey Shumkin, Junio C Hamano
In-Reply-To: <cover.1359018188.git.Alex.Crezoff@gmail.com>
The expected SHA-1 digests are always available in variables. Use
them instead of hardcoding.
Signed-off-by: Alexey Shumkin <Alex.Crezoff@gmail.com>
---
t/t6006-rev-list-format.sh | 130 +++++++++++++++++++++++++--------------------
1 file changed, 72 insertions(+), 58 deletions(-)
diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh
index f94f0c4..c248509 100755
--- a/t/t6006-rev-list-format.sh
+++ b/t/t6006-rev-list-format.sh
@@ -6,8 +6,19 @@ test_description='git rev-list --pretty=format test'
test_tick
test_expect_success 'setup' '
-touch foo && git add foo && git commit -m "added foo" &&
- echo changed >foo && git commit -a -m "changed foo"
+ touch foo &&
+ git add foo &&
+ git commit -m "added foo" &&
+ head1=$(git rev-parse --verify HEAD) &&
+ head1_7=$(echo $head1 | cut -c1-7) &&
+ echo changed >foo &&
+ git commit -a -m "changed foo" &&
+ head2=$(git rev-parse --verify HEAD) &&
+ head2_7=$(echo $head2 | cut -c1-7) &&
+ head2_parent=$(git cat-file -p HEAD | grep parent | cut -f 2 -d" ") &&
+ head2_parent_7=$(echo $head2_parent | cut -c1-7) &&
+ tree2=$(git cat-file -p HEAD | grep tree | cut -f 2 -d" ") &&
+ tree2_7=$(echo $tree2 | cut -c1-7)
'
# usage: test_format name format_string <expected_output
@@ -19,49 +30,49 @@ test_cmp expect.$1 output.$1
"
}
-test_format percent %%h <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
+test_format percent %%h <<EOF
+commit $head2
%h
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+commit $head1
%h
EOF
-test_format hash %H%n%h <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
-131a310eb913d107dd3c09a65d1651175898735d
-131a310
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
-86c75cfd708a0e5868dc876ed5b8bb66c80b4873
-86c75cf
+test_format hash %H%n%h <<EOF
+commit $head2
+$head2
+$head2_7
+commit $head1
+$head1
+$head1_7
EOF
-test_format tree %T%n%t <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
-fe722612f26da5064c32ca3843aa154bdb0b08a0
-fe72261
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+test_format tree %T%n%t <<EOF
+commit $head2
+$tree2
+$tree2_7
+commit $head1
4d5fcadc293a348e88f777dc0920f11e7d71441c
4d5fcad
EOF
-test_format parents %P%n%p <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
-86c75cfd708a0e5868dc876ed5b8bb66c80b4873
-86c75cf
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+test_format parents %P%n%p <<EOF
+commit $head2
+$head1
+$head2_parent_7
+commit $head1
EOF
# we don't test relative here
-test_format author %an%n%ae%n%ad%n%aD%n%at <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
+test_format author %an%n%ae%n%ad%n%aD%n%at <<EOF
+commit $head2
A U Thor
author@example.com
Thu Apr 7 15:13:13 2005 -0700
Thu, 7 Apr 2005 15:13:13 -0700
1112911993
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+commit $head1
A U Thor
author@example.com
Thu Apr 7 15:13:13 2005 -0700
@@ -69,14 +80,14 @@ Thu, 7 Apr 2005 15:13:13 -0700
1112911993
EOF
-test_format committer %cn%n%ce%n%cd%n%cD%n%ct <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
+test_format committer %cn%n%ce%n%cd%n%cD%n%ct <<EOF
+commit $head2
C O Mitter
committer@example.com
Thu Apr 7 15:13:13 2005 -0700
Thu, 7 Apr 2005 15:13:13 -0700
1112911993
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+commit $head1
C O Mitter
committer@example.com
Thu Apr 7 15:13:13 2005 -0700
@@ -84,21 +95,21 @@ Thu, 7 Apr 2005 15:13:13 -0700
1112911993
EOF
-test_format encoding %e <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+test_format encoding %e <<EOF
+commit $head2
+commit $head1
EOF
-test_format subject %s <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
+test_format subject %s <<EOF
+commit $head2
changed foo
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+commit $head1
added foo
EOF
-test_format body %b <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+test_format body %b <<EOF
+commit $head2
+commit $head1
EOF
test_format raw-body %B <<'EOF'
@@ -110,17 +121,17 @@ added foo
EOF
-test_format colors %Credfoo%Cgreenbar%Cbluebaz%Cresetxyzzy <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
+test_format colors %Credfoo%Cgreenbar%Cbluebaz%Cresetxyzzy <<EOF
+commit $head2
^[[31mfoo^[[32mbar^[[34mbaz^[[mxyzzy
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+commit $head1
^[[31mfoo^[[32mbar^[[34mbaz^[[mxyzzy
EOF
-test_format advanced-colors '%C(red yellow bold)foo%C(reset)' <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
+test_format advanced-colors '%C(red yellow bold)foo%C(reset)' <<EOF
+commit $head2
^[[1;31;43mfoo^[[m
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+commit $head1
^[[1;31;43mfoo^[[m
EOF
@@ -131,39 +142,42 @@ This commit message is much longer than the others,
and it will be encoded in iso8859-1. We should therefore
include an iso8859 character: ¡bueno!
EOF
+
test_expect_success 'setup complex body' '
-git config i18n.commitencoding iso8859-1 &&
- echo change2 >foo && git commit -a -F commit-msg
+ git config i18n.commitencoding iso8859-1 &&
+ echo change2 >foo && git commit -a -F commit-msg &&
+ head3=$(git rev-parse --verify HEAD) &&
+ head3_7=$(echo $head3 | cut -c1-7)
'
-test_format complex-encoding %e <<'EOF'
-commit f58db70b055c5718631e5c61528b28b12090cdea
+test_format complex-encoding %e <<EOF
+commit $head3
iso8859-1
-commit 131a310eb913d107dd3c09a65d1651175898735d
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+commit $head2
+commit $head1
EOF
-test_format complex-subject %s <<'EOF'
-commit f58db70b055c5718631e5c61528b28b12090cdea
+test_format complex-subject %s <<EOF
+commit $head3
Test printing of complex bodies
-commit 131a310eb913d107dd3c09a65d1651175898735d
+commit $head2
changed foo
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+commit $head1
added foo
EOF
-test_format complex-body %b <<'EOF'
-commit f58db70b055c5718631e5c61528b28b12090cdea
+test_format complex-body %b <<EOF
+commit $head3
This commit message is much longer than the others,
and it will be encoded in iso8859-1. We should therefore
include an iso8859 character: ¡bueno!
-commit 131a310eb913d107dd3c09a65d1651175898735d
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+commit $head2
+commit $head1
EOF
test_expect_success '%x00 shows NUL' '
- echo >expect commit f58db70b055c5718631e5c61528b28b12090cdea &&
+ echo >expect commit $head3 &&
echo >>expect fooQbar &&
git rev-list -1 --format=foo%x00bar HEAD >actual.nul &&
nul_to_q <actual.nul >actual &&
--
1.8.1.1.10.g9255f3f
^ permalink raw reply related
* [PATCH v4 2/4] t7102 (reset): refactoring: don't hardcode SHA-1 in expected outputs
From: Alexey Shumkin @ 2013-01-24 9:10 UTC (permalink / raw)
To: git; +Cc: Alexey Shumkin, Junio C Hamano
In-Reply-To: <cover.1359018188.git.Alex.Crezoff@gmail.com>
The expected SHA-1 digests are always available in variables. Use
them instead of hardcoding.
Signed-off-by: Alexey Shumkin <Alex.Crezoff@gmail.com>
---
t/t7102-reset.sh | 41 +++++++++++++++++++++--------------------
1 file changed, 21 insertions(+), 20 deletions(-)
diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh
index b096dc8..cf492f4 100755
--- a/t/t7102-reset.sh
+++ b/t/t7102-reset.sh
@@ -28,7 +28,8 @@ test_expect_success 'creating initial files and commits' '
echo "1st line 2nd file" >secondfile &&
echo "2nd line 2nd file" >>secondfile &&
- git commit -a -m "modify 2nd file"
+ git commit -a -m "modify 2nd file" &&
+ head5=$(git rev-parse --verify HEAD)
'
# git log --pretty=oneline # to see those SHA1 involved
@@ -56,7 +57,7 @@ test_expect_success 'giving a non existing revision should fail' '
test_must_fail git reset --mixed aaaaaa &&
test_must_fail git reset --soft aaaaaa &&
test_must_fail git reset --hard aaaaaa &&
- check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
+ check_changes $head5
'
test_expect_success 'reset --soft with unmerged index should fail' '
@@ -74,7 +75,7 @@ test_expect_success \
test_must_fail git reset --hard -- first &&
test_must_fail git reset --soft HEAD^ -- first &&
test_must_fail git reset --hard HEAD^ -- first &&
- check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
+ check_changes $head5
'
test_expect_success 'giving unrecognized options should fail' '
@@ -86,7 +87,7 @@ test_expect_success 'giving unrecognized options should fail' '
test_must_fail git reset --soft -o &&
test_must_fail git reset --hard --other &&
test_must_fail git reset --hard -o &&
- check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
+ check_changes $head5
'
test_expect_success \
@@ -110,7 +111,7 @@ test_expect_success \
git checkout master &&
git branch -D branch1 branch2 &&
- check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
+ check_changes $head5
'
test_expect_success \
@@ -133,27 +134,27 @@ test_expect_success \
git checkout master &&
git branch -D branch3 branch4 &&
- check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
+ check_changes $head5
'
test_expect_success \
'resetting to HEAD with no changes should succeed and do nothing' '
git reset --hard &&
- check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc &&
+ check_changes $head5 &&
git reset --hard HEAD &&
- check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc &&
+ check_changes $head5 &&
git reset --soft &&
- check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc &&
+ check_changes $head5 &&
git reset --soft HEAD &&
- check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc &&
+ check_changes $head5 &&
git reset --mixed &&
- check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc &&
+ check_changes $head5 &&
git reset --mixed HEAD &&
- check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc &&
+ check_changes $head5 &&
git reset &&
- check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc &&
+ check_changes $head5 &&
git reset HEAD &&
- check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
+ check_changes $head5
'
>.diff_expect
@@ -176,7 +177,7 @@ test_expect_success '--soft reset only should show changes in diff --cached' '
git reset --soft HEAD^ &&
check_changes d1a4bc3abce4829628ae2dcb0d60ef3d1a78b1c4 &&
test "$(git rev-parse ORIG_HEAD)" = \
- 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
+ $head5
'
>.diff_expect
@@ -193,7 +194,7 @@ test_expect_success \
git commit -a -C ORIG_HEAD &&
check_changes 3d3b7be011a58ca0c179ae45d94e6c83c0b0cd0d &&
test "$(git rev-parse ORIG_HEAD)" = \
- 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
+ $head5
'
>.diff_expect
@@ -303,7 +304,7 @@ test_expect_success 'redoing the last two commits should succeed' '
echo "1st line 2nd file" >secondfile &&
echo "2nd line 2nd file" >>secondfile &&
git commit -a -m "modify 2nd file" &&
- check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
+ check_changes $head5
'
>.diff_expect
@@ -341,15 +342,15 @@ EOF
test_expect_success \
'--hard reset to ORIG_HEAD should clear a fast-forward merge' '
git reset --hard HEAD^ &&
- check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc &&
+ check_changes $head5 &&
git pull . branch1 &&
git reset --hard ORIG_HEAD &&
- check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc &&
+ check_changes $head5 &&
git checkout master &&
git branch -D branch1 branch2 &&
- check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
+ check_changes $head5
'
cat > expect << EOF
--
1.8.1.1.10.g9255f3f
^ permalink raw reply related
* [PATCH v4 3/4] pretty: Add failing tests: user format ignores i18n.logOutputEncoding setting
From: Alexey Shumkin @ 2013-01-24 9:10 UTC (permalink / raw)
To: git; +Cc: Alexey Shumkin, Junio C Hamano
In-Reply-To: <cover.1359018188.git.Alex.Crezoff@gmail.com>
The following two commands are expected to give the same output to a terminal:
$ git log --oneline --no-color
$ git log --pretty=format:'%h %s'
However, the former pays attention to i18n.logOutputEncoding
configuration, while the latter does not when it format "%s".
Log messages written in an encoding i18n.commitEncoding which differs
from terminal encoding are shown corrupted with the latter even
when i18n.logOutputEncoding and terminal encoding are the same.
The same corruption is true for
$ git diff --submodule=log
and
$ git rev-list --pretty=format:%s HEAD
and
$ git reset --hard
Signed-off-by: Alexey Shumkin <Alex.Crezoff@gmail.com>
---
t/t4041-diff-submodule-option.sh | 33 ++++++++-------
t/t4205-log-pretty-formats.sh | 43 +++++++++++++++----
t/t6006-rev-list-format.sh | 90 ++++++++++++++++++++++++++--------------
t/t7102-reset.sh | 32 +++++++++++---
4 files changed, 138 insertions(+), 60 deletions(-)
diff --git a/t/t4041-diff-submodule-option.sh b/t/t4041-diff-submodule-option.sh
index 32d4a60..e7d6363 100755
--- a/t/t4041-diff-submodule-option.sh
+++ b/t/t4041-diff-submodule-option.sh
@@ -1,6 +1,7 @@
#!/bin/sh
#
# Copyright (c) 2009 Jens Lehmann, based on t7401 by Ping Yin
+# Copyright (c) 2011 Alexey Shumkin (+ non-UTF-8 commit encoding tests)
#
test_description='Support for verbose submodule differences in git diff
@@ -10,6 +11,7 @@ This test tries to verify the sanity of the --submodule option of git diff.
. ./test-lib.sh
+added=$(printf "\320\264\320\276\320\261\320\260\320\262\320\273\320\265\320\275")
add_file () {
(
cd "$1" &&
@@ -19,7 +21,8 @@ add_file () {
echo "$name" >"$name" &&
git add "$name" &&
test_tick &&
- git commit -m "Add $name" || exit
+ msg_added_cp1251=$(echo "Add $name ($added $name)" | iconv -f utf-8 -t cp1251) &&
+ git -c 'i18n.commitEncoding=cp1251' commit -m "$msg_added_cp1251"
done >/dev/null &&
git rev-parse --short --verify HEAD
)
@@ -89,29 +92,29 @@ test_expect_success 'diff.submodule does not affect plumbing' '
commit_file sm1 &&
head2=$(add_file sm1 foo3)
-test_expect_success 'modified submodule(forward)' '
+test_expect_failure 'modified submodule(forward)' '
git diff-index -p --submodule=log HEAD >actual &&
cat >expected <<-EOF &&
Submodule sm1 $head1..$head2:
- > Add foo3
+ > Add foo3 ($added foo3)
EOF
test_cmp expected actual
'
-test_expect_success 'modified submodule(forward)' '
+test_expect_failure 'modified submodule(forward)' '
git diff --submodule=log >actual &&
cat >expected <<-EOF &&
Submodule sm1 $head1..$head2:
- > Add foo3
+ > Add foo3 ($added foo3)
EOF
test_cmp expected actual
'
-test_expect_success 'modified submodule(forward) --submodule' '
+test_expect_failure 'modified submodule(forward) --submodule' '
git diff --submodule >actual &&
cat >expected <<-EOF &&
Submodule sm1 $head1..$head2:
- > Add foo3
+ > Add foo3 ($added foo3)
EOF
test_cmp expected actual
'
@@ -138,25 +141,25 @@ head3=$(
git rev-parse --short --verify HEAD
)
-test_expect_success 'modified submodule(backward)' '
+test_expect_failure 'modified submodule(backward)' '
git diff-index -p --submodule=log HEAD >actual &&
cat >expected <<-EOF &&
Submodule sm1 $head2..$head3 (rewind):
- < Add foo3
- < Add foo2
+ < Add foo3 ($added foo3)
+ < Add foo2 ($added foo2)
EOF
test_cmp expected actual
'
head4=$(add_file sm1 foo4 foo5)
-test_expect_success 'modified submodule(backward and forward)' '
+test_expect_failure 'modified submodule(backward and forward)' '
git diff-index -p --submodule=log HEAD >actual &&
cat >expected <<-EOF &&
Submodule sm1 $head2...$head4:
- > Add foo5
- > Add foo4
- < Add foo3
- < Add foo2
+ > Add foo5 ($added foo5)
+ > Add foo4 ($added foo4)
+ < Add foo3 ($added foo3)
+ < Add foo2 ($added foo2)
EOF
test_cmp expected actual
'
diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh
index 98a43d4..76ffa0d 100755
--- a/t/t4205-log-pretty-formats.sh
+++ b/t/t4205-log-pretty-formats.sh
@@ -1,20 +1,31 @@
#!/bin/sh
#
# Copyright (c) 2010, Will Palmer
+# Copyright (c) 2011, Alexey Shumkin (+ non-UTF-8 commit encoding tests)
#
test_description='Test pretty formats'
. ./test-lib.sh
+commit_msg() {
+ msg=$(printf "initial \320\272\320\276\320\274\320\274\320\270\321\202")
+ if test -n "$1"; then
+ msg=$(echo $msg | iconv -f utf-8 -t $1)
+ fi
+ echo $msg
+}
+
test_expect_success 'set up basic repos' '
>foo &&
>bar &&
git add foo &&
test_tick &&
- git commit -m initial &&
+ git config i18n.commitEncoding cp1251 &&
+ git commit -m "$(commit_msg cp1251)" &&
git add bar &&
test_tick &&
- git commit -m "add bar"
+ git commit -m "add bar" &&
+ git config --unset i18n.commitEncoding
'
test_expect_success 'alias builtin format' '
@@ -38,6 +49,20 @@ test_expect_success 'alias user-defined format' '
test_cmp expected actual
'
+test_expect_success 'alias user-defined tformat with %s (cp1251 encoding)' '
+ git config i18n.logOutputEncoding cp1251 &&
+ git log --oneline >expected-s &&
+ git log --pretty="tformat:%h %s" >actual-s &&
+ git config --unset i18n.logOutputEncoding &&
+ test_cmp expected-s actual-s
+'
+
+test_expect_failure 'alias user-defined tformat with %s (utf-8 encoding)' '
+ git log --oneline >expected-s &&
+ git log --pretty="tformat:%h %s" >actual-s &&
+ test_cmp expected-s actual-s
+'
+
test_expect_success 'alias user-defined tformat' '
git log --pretty="tformat:%h" >expected &&
git config pretty.test-alias "tformat:%h" &&
@@ -71,22 +96,22 @@ test_expect_success 'alias loop' '
test_must_fail git log --pretty=test-foo
'
-test_expect_success 'NUL separation' '
- printf "add bar\0initial" >expected &&
+test_expect_failure 'NUL separation' '
+ printf "add bar\0$(commit_msg)" >expected &&
git log -z --pretty="format:%s" >actual &&
test_cmp expected actual
'
-test_expect_success 'NUL termination' '
- printf "add bar\0initial\0" >expected &&
+test_expect_failure 'NUL termination' '
+ printf "add bar\0$(commit_msg)\0" >expected &&
git log -z --pretty="tformat:%s" >actual &&
test_cmp expected actual
'
-test_expect_success 'NUL separation with --stat' '
+test_expect_failure 'NUL separation with --stat' '
stat0_part=$(git diff --stat HEAD^ HEAD) &&
stat1_part=$(git diff-tree --no-commit-id --stat --root HEAD^) &&
- printf "add bar\n$stat0_part\n\0initial\n$stat1_part\n" >expected &&
+ printf "add bar\n$stat0_part\n\0$(commit_msg)\n$stat1_part\n" >expected &&
git log -z --stat --pretty="format:%s" >actual &&
test_i18ncmp expected actual
'
@@ -94,7 +119,7 @@ test_expect_success 'NUL separation with --stat' '
test_expect_failure 'NUL termination with --stat' '
stat0_part=$(git diff --stat HEAD^ HEAD) &&
stat1_part=$(git diff-tree --no-commit-id --stat --root HEAD^) &&
- printf "add bar\n$stat0_part\n\0initial\n$stat1_part\n\0" >expected &&
+ printf "add bar\n$stat0_part\n\0$(commit_msg)\n$stat1_part\n0" >expected &&
git log -z --stat --pretty="tformat:%s" >actual &&
test_i18ncmp expected actual
'
diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh
index c248509..4db43a4 100755
--- a/t/t6006-rev-list-format.sh
+++ b/t/t6006-rev-list-format.sh
@@ -1,33 +1,54 @@
#!/bin/sh
+# Copyright (c) 2009 Jens Lehmann
+# Copyright (c) 2011 Alexey Shumkin (+ non-UTF-8 commit encoding tests)
+
test_description='git rev-list --pretty=format test'
. ./test-lib.sh
test_tick
+added=$(printf "added (\320\264\320\276\320\261\320\260\320\262\320\273\320\265\320\275) foo")
+added_cp1251=$(echo "$added" | iconv -f utf-8 -t cp1251)
+changed=$(printf "changed (\320\264\320\276\320\261\320\260\320\262\320\273\320\265\320\275) foo")
+changed_cp1251=$(echo "$changed" | iconv -f utf-8 -t cp1251)
+
test_expect_success 'setup' '
touch foo &&
git add foo &&
- git commit -m "added foo" &&
+ git config i18n.commitEncoding cp1251 &&
+ git commit -m "$added_cp1251" &&
head1=$(git rev-parse --verify HEAD) &&
head1_7=$(echo $head1 | cut -c1-7) &&
- echo changed >foo &&
- git commit -a -m "changed foo" &&
+ echo "$changed" > foo &&
+ git commit -a -m "$changed_cp1251" &&
head2=$(git rev-parse --verify HEAD) &&
head2_7=$(echo $head2 | cut -c1-7) &&
+ tree2=$(git cat-file -p HEAD | grep tree | cut -f 2 -d" ") &&
+ tree2_7=$(echo $tree2 | cut -c1-7) &&
head2_parent=$(git cat-file -p HEAD | grep parent | cut -f 2 -d" ") &&
head2_parent_7=$(echo $head2_parent | cut -c1-7) &&
- tree2=$(git cat-file -p HEAD | grep tree | cut -f 2 -d" ") &&
- tree2_7=$(echo $tree2 | cut -c1-7)
+ git config --unset i18n.commitEncoding
'
# usage: test_format name format_string <expected_output
test_format() {
+ local must_fail=0
+ # if parameters count is more than 2 then test must fail
+ if [ $# -gt 2 ]; then
+ must_fail=1
+ # remove first parameter which is flag for test failure
+ shift
+ fi
cat >expect.$1
- test_expect_success "format $1" "
-git rev-list --pretty=format:'$2' master >output.$1 &&
-test_cmp expect.$1 output.$1
-"
+ name="format $1"
+ command="git rev-list --pretty=format:'$2' master >output.$1 &&
+test_cmp expect.$1 output.$1"
+ if [ $must_fail -eq 1 ]; then
+ test_expect_failure "$name" "$command"
+ else
+ test_expect_success "$name" "$command"
+ fi
}
test_format percent %%h <<EOF
@@ -95,16 +116,16 @@ Thu, 7 Apr 2005 15:13:13 -0700
1112911993
EOF
-test_format encoding %e <<EOF
+test_format failure encoding %e <<EOF
commit $head2
commit $head1
EOF
-test_format subject %s <<EOF
+test_format failure subject %s <<EOF
commit $head2
-changed foo
+$changed
commit $head1
-added foo
+$added
EOF
test_format body %b <<EOF
@@ -112,12 +133,12 @@ commit $head2
commit $head1
EOF
-test_format raw-body %B <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
-changed foo
+test_format failure raw-body %B <<EOF
+commit $head2
+$changed
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
-added foo
+commit $head1
+$added
EOF
@@ -135,16 +156,16 @@ commit $head1
^[[1;31;43mfoo^[[m
EOF
-cat >commit-msg <<'EOF'
+iconv -f utf-8 -t cp1251 > commit-msg <<EOF
Test printing of complex bodies
This commit message is much longer than the others,
-and it will be encoded in iso8859-1. We should therefore
-include an iso8859 character: ¡bueno!
+and it will be encoded in cp1251. We should therefore
+include an cp1251 character: так вот!
EOF
test_expect_success 'setup complex body' '
- git config i18n.commitencoding iso8859-1 &&
+ git config i18n.commitencoding cp1251 &&
echo change2 >foo && git commit -a -F commit-msg &&
head3=$(git rev-parse --verify HEAD) &&
head3_7=$(echo $head3 | cut -c1-7)
@@ -152,25 +173,32 @@ test_expect_success 'setup complex body' '
test_format complex-encoding %e <<EOF
commit $head3
-iso8859-1
+cp1251
commit $head2
+cp1251
commit $head1
+cp1251
EOF
-test_format complex-subject %s <<EOF
+# unset commit encoding config
+# otherwise %e does not print encoding value
+# and following test fails
+git config --unset i18n.commitencoding
+
+test_format failure complex-subject %s <<EOF
commit $head3
Test printing of complex bodies
commit $head2
-changed foo
+$changed
commit $head1
-added foo
+$added
EOF
-test_format complex-body %b <<EOF
+test_format failure complex-body %b <<EOF
commit $head3
This commit message is much longer than the others,
-and it will be encoded in iso8859-1. We should therefore
-include an iso8859 character: ¡bueno!
+and it will be encoded in cp1251. We should therefore
+include an cp1251 character: так вот!
commit $head2
commit $head1
@@ -224,12 +252,12 @@ test_expect_success 'add LF before non-empty (2)' '
test_expect_success 'add SP before non-empty (1)' '
git show -s --pretty=format:"%s% bThanks" HEAD^^ >actual &&
- test $(wc -w <actual) = 2
+ test $(wc -w <actual) = 3
'
test_expect_success 'add SP before non-empty (2)' '
git show -s --pretty=format:"%s% sThanks" HEAD^^ >actual &&
- test $(wc -w <actual) = 4
+ test $(wc -w <actual) = 6
'
test_expect_success '--abbrev' '
diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh
index cf492f4..699c824 100755
--- a/t/t7102-reset.sh
+++ b/t/t7102-reset.sh
@@ -9,6 +9,14 @@ Documented tests for git reset'
. ./test-lib.sh
+commit_msg() {
+ msg=$(printf "modify 2nd file (\320\270\320\267\320\274\320\265\320\275\321\221\320\275 \321\204\320\260\320\271\320\273)")
+ if test -n "$1"; then
+ msg=$(echo $msg | iconv -f utf-8 -t $1)
+ fi
+ echo $msg
+}
+
test_expect_success 'creating initial files and commits' '
test_tick &&
echo "1st file" >first &&
@@ -28,7 +36,7 @@ test_expect_success 'creating initial files and commits' '
echo "1st line 2nd file" >secondfile &&
echo "2nd line 2nd file" >>secondfile &&
- git commit -a -m "modify 2nd file" &&
+ git -c "i18n.commitEncoding=cp1251" commit -a -m "$(commit_msg cp1251)" &&
head5=$(git rev-parse --verify HEAD)
'
# git log --pretty=oneline # to see those SHA1 involved
@@ -44,6 +52,20 @@ check_changes () {
done | test_cmp .cat_expect -
}
+test_expect_failure 'reset --hard message' '
+ hex=$(git log -1 --format="%h") &&
+ git reset --hard > .actual &&
+ echo HEAD is now at $hex $(commit_msg) > .expected &&
+ test_cmp .actual .expected
+'
+
+test_expect_success 'reset --hard message (cp1251 logoutencoding)' '
+ hex=$(git log -1 --format="%h") &&
+ git -c "i18n.logOutputEncoding=cp1251" reset --hard > .actual &&
+ echo HEAD is now at $hex $(commit_msg cp1251) > .expected &&
+ test_cmp .actual .expected
+'
+
>.diff_expect
>.cached_expect
cat >.cat_expect <<EOF
@@ -192,7 +214,7 @@ test_expect_success \
'changing files and redo the last commit should succeed' '
echo "3rd line 2nd file" >>secondfile &&
git commit -a -C ORIG_HEAD &&
- check_changes 3d3b7be011a58ca0c179ae45d94e6c83c0b0cd0d &&
+ check_changes f06f78b8dd468c722952b77569dd0db212442c25 &&
test "$(git rev-parse ORIG_HEAD)" = \
$head5
'
@@ -211,7 +233,7 @@ test_expect_success \
git reset --hard HEAD~2 &&
check_changes ddaefe00f1da16864591c61fdc7adb5d7cd6b74e &&
test "$(git rev-parse ORIG_HEAD)" = \
- 3d3b7be011a58ca0c179ae45d94e6c83c0b0cd0d
+ f06f78b8dd468c722952b77569dd0db212442c25
'
>.diff_expect
@@ -303,7 +325,7 @@ test_expect_success 'redoing the last two commits should succeed' '
echo "1st line 2nd file" >secondfile &&
echo "2nd line 2nd file" >>secondfile &&
- git commit -a -m "modify 2nd file" &&
+ git -c "i18n.commitEncoding=cp1251" commit -a -m "$(commit_msg cp1251)" &&
check_changes $head5
'
@@ -329,7 +351,7 @@ test_expect_success '--hard reset to HEAD should clear a failed merge' '
test_must_fail git pull . branch1 &&
git reset --hard &&
- check_changes 77abb337073fb4369a7ad69ff6f5ec0e4d6b54bb
+ check_changes f26fb896db2344fe158ce3720249e1df4d26174b
'
>.diff_expect
--
1.8.1.1.10.g9255f3f
^ permalink raw reply related
* [PATCH v4 4/4] pretty: user format ignores i18n.logOutputEncoding setting
From: Alexey Shumkin @ 2013-01-24 9:10 UTC (permalink / raw)
To: git; +Cc: Alexey Shumkin, Junio C Hamano, Alexey Shumkin
In-Reply-To: <cover.1359018188.git.Alex.Crezoff@gmail.com>
From: Alexey Shumkin <zapped@mail.ru>
The following two commands are expected to give the same output to a terminal:
$ git log --oneline --no-color
$ git log --pretty=format:'%h %s'
However, the former pays attention to i18n.logOutputEncoding
configuration, while the latter does not when it format "%s".
Log messages written in an encoding i18n.commitEncoding which differs
from terminal encoding are shown corrupted with the latter even
when i18n.logOutputEncoding and terminal encoding are the same.
The same corruption is true for
$ git diff --submodule=log
and
$ git rev-list --pretty=format:%s HEAD
and
$ git reset --hard
Signed-off-by: Alexey Shumkin <Alex.Crezoff@gmail.com>
---
builtin/reset.c | 8 ++++++--
builtin/rev-list.c | 1 +
builtin/shortlog.c | 1 +
log-tree.c | 1 +
submodule.c | 3 +++
t/t4041-diff-submodule-option.sh | 10 +++++-----
t/t4205-log-pretty-formats.sh | 8 ++++----
t/t6006-rev-list-format.sh | 10 +++++-----
t/t7102-reset.sh | 2 +-
9 files changed, 27 insertions(+), 17 deletions(-)
diff --git a/builtin/reset.c b/builtin/reset.c
index 915cc9f..11c0aa4 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -100,11 +100,15 @@ static int reset_index_file(const unsigned char *sha1, int reset_type, int quiet
static void print_new_head_line(struct commit *commit)
{
- const char *hex, *body;
+ const char *hex, *body, *encoding;
hex = find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV);
printf(_("HEAD is now at %s"), hex);
- body = strstr(commit->buffer, "\n\n");
+ encoding = get_log_output_encoding();
+ body = logmsg_reencode(commit, encoding);
+ if (!body)
+ body = commit->buffer;
+ body = strstr(body, "\n\n");
if (body) {
const char *eol;
size_t len;
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index 67701be..a5ec30d 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -111,6 +111,7 @@ static void show_commit(struct commit *commit, void *data)
ctx.date_mode = revs->date_mode;
ctx.date_mode_explicit = revs->date_mode_explicit;
ctx.fmt = revs->commit_format;
+ ctx.output_encoding = get_log_output_encoding();
pretty_print_commit(&ctx, commit, &buf);
if (revs->graph) {
if (buf.len) {
diff --git a/builtin/shortlog.c b/builtin/shortlog.c
index 8360514..23c05cd 100644
--- a/builtin/shortlog.c
+++ b/builtin/shortlog.c
@@ -163,6 +163,7 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)
ctx.subject = "";
ctx.after_subject = "";
ctx.date_mode = DATE_NORMAL;
+ ctx.output_encoding = get_log_output_encoding();
pretty_print_commit(&ctx, commit, &ufbuf);
buffer = ufbuf.buf;
} else if (*buffer) {
diff --git a/log-tree.c b/log-tree.c
index 4f86def..e1ff3a5 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -671,6 +671,7 @@ void show_log(struct rev_info *opt)
ctx.preserve_subject = opt->preserve_subject;
ctx.reflog_info = opt->reflog_info;
ctx.fmt = opt->commit_format;
+ ctx.output_encoding = get_log_output_encoding();
pretty_print_commit(&ctx, commit, &msgbuf);
if (opt->add_signoff)
diff --git a/submodule.c b/submodule.c
index 2f55436..8e42750 100644
--- a/submodule.c
+++ b/submodule.c
@@ -222,10 +222,13 @@ static void print_submodule_summary(struct rev_info *rev, FILE *f,
static const char format[] = " %m %s";
struct strbuf sb = STRBUF_INIT;
struct commit *commit;
+ const char *log_output_encoding;
+ log_output_encoding = get_log_output_encoding();
while ((commit = get_revision(rev))) {
struct pretty_print_context ctx = {0};
ctx.date_mode = rev->date_mode;
+ ctx.output_encoding = log_output_encoding;
strbuf_setlen(&sb, 0);
if (commit->object.flags & SYMMETRIC_LEFT) {
if (del)
diff --git a/t/t4041-diff-submodule-option.sh b/t/t4041-diff-submodule-option.sh
index e7d6363..39f0609 100755
--- a/t/t4041-diff-submodule-option.sh
+++ b/t/t4041-diff-submodule-option.sh
@@ -92,7 +92,7 @@ test_expect_success 'diff.submodule does not affect plumbing' '
commit_file sm1 &&
head2=$(add_file sm1 foo3)
-test_expect_failure 'modified submodule(forward)' '
+test_expect_success 'modified submodule(forward)' '
git diff-index -p --submodule=log HEAD >actual &&
cat >expected <<-EOF &&
Submodule sm1 $head1..$head2:
@@ -101,7 +101,7 @@ test_expect_failure 'modified submodule(forward)' '
test_cmp expected actual
'
-test_expect_failure 'modified submodule(forward)' '
+test_expect_success 'modified submodule(forward)' '
git diff --submodule=log >actual &&
cat >expected <<-EOF &&
Submodule sm1 $head1..$head2:
@@ -110,7 +110,7 @@ test_expect_failure 'modified submodule(forward)' '
test_cmp expected actual
'
-test_expect_failure 'modified submodule(forward) --submodule' '
+test_expect_success 'modified submodule(forward) --submodule' '
git diff --submodule >actual &&
cat >expected <<-EOF &&
Submodule sm1 $head1..$head2:
@@ -141,7 +141,7 @@ head3=$(
git rev-parse --short --verify HEAD
)
-test_expect_failure 'modified submodule(backward)' '
+test_expect_success 'modified submodule(backward)' '
git diff-index -p --submodule=log HEAD >actual &&
cat >expected <<-EOF &&
Submodule sm1 $head2..$head3 (rewind):
@@ -152,7 +152,7 @@ test_expect_failure 'modified submodule(backward)' '
'
head4=$(add_file sm1 foo4 foo5)
-test_expect_failure 'modified submodule(backward and forward)' '
+test_expect_success 'modified submodule(backward and forward)' '
git diff-index -p --submodule=log HEAD >actual &&
cat >expected <<-EOF &&
Submodule sm1 $head2...$head4:
diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh
index 76ffa0d..54a9704 100755
--- a/t/t4205-log-pretty-formats.sh
+++ b/t/t4205-log-pretty-formats.sh
@@ -57,7 +57,7 @@ test_expect_success 'alias user-defined tformat with %s (cp1251 encoding)' '
test_cmp expected-s actual-s
'
-test_expect_failure 'alias user-defined tformat with %s (utf-8 encoding)' '
+test_expect_success 'alias user-defined tformat with %s (utf-8 encoding)' '
git log --oneline >expected-s &&
git log --pretty="tformat:%h %s" >actual-s &&
test_cmp expected-s actual-s
@@ -96,19 +96,19 @@ test_expect_success 'alias loop' '
test_must_fail git log --pretty=test-foo
'
-test_expect_failure 'NUL separation' '
+test_expect_success 'NUL separation' '
printf "add bar\0$(commit_msg)" >expected &&
git log -z --pretty="format:%s" >actual &&
test_cmp expected actual
'
-test_expect_failure 'NUL termination' '
+test_expect_success 'NUL termination' '
printf "add bar\0$(commit_msg)\0" >expected &&
git log -z --pretty="tformat:%s" >actual &&
test_cmp expected actual
'
-test_expect_failure 'NUL separation with --stat' '
+test_expect_success 'NUL separation with --stat' '
stat0_part=$(git diff --stat HEAD^ HEAD) &&
stat1_part=$(git diff-tree --no-commit-id --stat --root HEAD^) &&
printf "add bar\n$stat0_part\n\0$(commit_msg)\n$stat1_part\n" >expected &&
diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh
index 4db43a4..006e6ab 100755
--- a/t/t6006-rev-list-format.sh
+++ b/t/t6006-rev-list-format.sh
@@ -116,12 +116,12 @@ Thu, 7 Apr 2005 15:13:13 -0700
1112911993
EOF
-test_format failure encoding %e <<EOF
+test_format encoding %e <<EOF
commit $head2
commit $head1
EOF
-test_format failure subject %s <<EOF
+test_format subject %s <<EOF
commit $head2
$changed
commit $head1
@@ -133,7 +133,7 @@ commit $head2
commit $head1
EOF
-test_format failure raw-body %B <<EOF
+test_format raw-body %B <<EOF
commit $head2
$changed
@@ -185,7 +185,7 @@ EOF
# and following test fails
git config --unset i18n.commitencoding
-test_format failure complex-subject %s <<EOF
+test_format complex-subject %s <<EOF
commit $head3
Test printing of complex bodies
commit $head2
@@ -194,7 +194,7 @@ commit $head1
$added
EOF
-test_format failure complex-body %b <<EOF
+test_format complex-body %b <<EOF
commit $head3
This commit message is much longer than the others,
and it will be encoded in cp1251. We should therefore
diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh
index 699c824..ea14c97 100755
--- a/t/t7102-reset.sh
+++ b/t/t7102-reset.sh
@@ -52,7 +52,7 @@ check_changes () {
done | test_cmp .cat_expect -
}
-test_expect_failure 'reset --hard message' '
+test_expect_success 'reset --hard message' '
hex=$(git log -1 --format="%h") &&
git reset --hard > .actual &&
echo HEAD is now at $hex $(commit_msg) > .expected &&
--
1.8.1.1.10.g9255f3f
^ permalink raw reply related
* Re: [PATCH v3 0/2] Make git-svn work with gitdir links
From: Eric Wong @ 2013-01-24 10:14 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Barry Wardell, git
In-Reply-To: <7vehhbdu8y.fsf@alter.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> wrote:
> Eric Wong <normalperson@yhbt.net> writes:
>
> > diff --git a/git-svn.perl b/git-svn.perl
> > index c232798..e5bd292 100755
> > --- a/git-svn.perl
> > +++ b/git-svn.perl
> > @@ -332,11 +332,13 @@ if ($cmd && $cmd =~ /(?:clone|init|multi-init)$/) {
> > $ENV{GIT_DIR} = command_oneline([qw/rev-parse --git-dir/]);
> > } "Unable to find .git directory\n";
> > my $cdup = undef;
> > + my $git_dir = delete $ENV{GIT_DIR};
> > git_cmd_try {
> > $cdup = command_oneline(qw/rev-parse --show-cdup/);
> > chomp $cdup if ($cdup);
> > $cdup = "." unless ($cdup && length $cdup);
> > - } "Already at toplevel, but $ENV{GIT_DIR} not found\n";
> > + } "Already at toplevel, but $git_dir not found\n";
> > + $ENV{GIT_DIR} = $git_dir;
> > chdir $cdup or die "Unable to chdir up to '$cdup'\n";
> > $_repository = Git->repository(Repository => $ENV{GIT_DIR});
> > }
>
> This does not look quite right, though.
>
> Can't the user have his own $GIT_DIR when this command is invoked?
> The first command_oneline() runs rev-parse with that environment and
> get the user specified value of GIT_DIR in $ENV{GIT_DIR}, but by
> doing a "delete" before running --show-cdup, you are not honoring
> that GIT_DIR (and GIT_WORK_TREE if exists) the user gave you. You
> already used that GIT_DIR when you asked rev-parse --git-dir to find
> what the GIT_DIR value should be, so you would be operating with
> values of $git_dir and $cdup that you discovered in an inconsistent
> way, no?
>
> Shouldn't it be more like this instead?
>
> my ($git_dir, $cdup) = undef;
> try {
> $git_dir = command_oneline(qw(rev-parse --git-dir));
> } "Unable to ...";
> try {
> $cdup = command_oneline(qw(rev-parse --show-cdup));
> ... tweak $cdup ...
> } "Unable to ...";
> if (defined $git_dir) { $ENV{GIT_DIR} = $git_dir; }
> chdir $cdup;
Thanks, I'll squash the following and push a new branch. I don't
believe the (defined $git_dir) check is necessary since we already
checked for errors with git_cmd_try.
diff --git a/git-svn.perl b/git-svn.perl
index e5bd292..b46795f 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -324,19 +324,18 @@ for (my $i = 0; $i < @ARGV; $i++) {
}
};
# make sure we're always running at the top-level working directory
if ($cmd && $cmd =~ /(?:clone|init|multi-init)$/) {
$ENV{GIT_DIR} ||= ".git";
} else {
+ my ($git_dir, $cdup);
git_cmd_try {
- $ENV{GIT_DIR} = command_oneline([qw/rev-parse --git-dir/]);
+ $git_dir = command_oneline([qw/rev-parse --git-dir/]);
} "Unable to find .git directory\n";
- my $cdup = undef;
- my $git_dir = delete $ENV{GIT_DIR};
git_cmd_try {
$cdup = command_oneline(qw/rev-parse --show-cdup/);
chomp $cdup if ($cdup);
$cdup = "." unless ($cdup && length $cdup);
} "Already at toplevel, but $git_dir not found\n";
$ENV{GIT_DIR} = $git_dir;
chdir $cdup or die "Unable to chdir up to '$cdup'\n";
--
Eric Wong
^ permalink raw reply related
* [PULL (updated)] git-svn updates for master
From: Eric Wong @ 2013-01-24 10:25 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Barry Wardell, Jonathan Nieder
In-Reply-To: <20130124013254.GB8096@dcvr.yhbt.net>
I've squashed the change I mentioned in
http://mid.gmane.org/20130124101417.GA22138@dcvr.yhbt.net
to Barry's commit, and added Jonathan's Reviewed-by to my cleanup
commit.
The following changes since commit ec3ae6ec46ed48383ae40643990f169b65a563cc:
Merge git://ozlabs.org/~paulus/gitk (2013-01-23 08:35:03 -0800)
are available in the git repository at:
git://bogomips.org/git-svn for-junio
for you to fetch changes up to bc93ceb7c5ec959ad275f575a3c49ff491337a8b:
git-svn: Simplify calculation of GIT_DIR (2013-01-24 10:21:23 +0000)
(My old master is unchanged.)
----------------------------------------------------------------
Barry Wardell (1):
git-svn: Simplify calculation of GIT_DIR
Eric Wong (1):
git-svn: cleanup sprintf usage for uppercasing hex
git-svn.perl | 37 ++++++++++++++-----------------------
perl/Git/SVN.pm | 4 ++--
perl/Git/SVN/Editor.pm | 2 +-
t/t9100-git-svn-basic.sh | 8 ++++++++
4 files changed, 25 insertions(+), 26 deletions(-)
--
Eric Wong
^ permalink raw reply
* Re: [PATCH] send-email: Honor multi-part email messages
From: Alexey Shumkin @ 2013-01-24 10:38 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <20110921001925.03a83d3a@zappedws>
Bump
^ permalink raw reply
* Re: [PATCH] mergetools: Add tortoisegitmerge helper
From: Sven Strickroth @ 2013-01-24 11:19 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Sebastian Schuberth, davvid, Jeff King
In-Reply-To: <50FCFBBB.2080305@tu-clausthal.de>
Am 21.01.2013 09:26 schrieb Sven Strickroth:
> - The TortoiseGit team renamed TortoiseMerge.exe to TortoiseGitMerge.exe
> (starting with 1.8.0) in order to make clear that this one has special
> support for git and prevent confusion with the TortoiseSVN TortoiseMerge
> version.
> - The tortoisemerge mergetool does not work with filenames which have
> a space in it. Fixing this required changes in git and also in
> TortoiseGitMerge; see https://github.com/msysgit/msysgit/issues/57.
>
> The new tortoisegitmerge helper was added so that people can still use
> TortoiseMerge from TortoiseSVN (and older TortoiseGit versions).
Any comments for this patch?
--
Best regards,
Sven Strickroth
PGP key id F5A9D4C4 @ any key-server
^ permalink raw reply
* Re: segmentation fault (nullpointer) with git log --submodule -p
From: Stefan Näwe @ 2013-01-24 12:11 UTC (permalink / raw)
To: Jeff King; +Cc: Armin, git@vger.kernel.org
In-Reply-To: <20130123200222.GB19832@sigill.intra.peff.net>
Am 23.01.2013 21:02, schrieb Jeff King:
> On Wed, Jan 23, 2013 at 03:38:16PM +0100, Armin wrote:
>
>> Hello dear git people.
>>
>> I experience a reproducible segmentation fault on one of my
>> repositories when doing a "git log --submodule -p", tested with newest
>> version on Arch Linux (git version 1.8.1.1) and built fresh (git
>> version 1.8.1.1.347.g9591fcc), tried on 2 seperate systems:
>>
>>
>> Program terminated with signal 11, Segmentation fault.
>> #0 0x00000000004b51e5 in parse_commit_header (context=0x7ffff69b6980) at pretty.c:752
>> 752 for (i = 0; msg[i]; i++) {
>> [...]
>> (gdb) l
>> 747 static void parse_commit_header(struct format_commit_context *context)
>> 748 {
>> 749 const char *msg = context->message;
>> 750 int i;
>> 751
>> 752 for (i = 0; msg[i]; i++) {
>> 753 int eol;
>> 754 for (eol = i; msg[eol] && msg[eol] != '\n'; eol++)
>> 755 ; /* do nothing */
>> 756
>> (gdb) p msg
>> $7 = <optimized out>
>> (gdb) p context->message
>> $8 = 0x0
>
> Yeah, that should definitely not be NULL. I can't reproduce here with a
> few simple examples, though.
>
> Does it fail with older versions of git? If so, can you bisect?
I did. My bisection told me this is the suspect:
ccdc603 (parse_object: try internal cache before reading object db)
My git-fu is not good enough to analyze that...
> Is it possible for you to make your repo available?
Unfortunately not. It crashes with one particular repos (using submodules)
that I can't make available but not with another which is available
at https://github.com/snaewe/super.git
HTH
Stefan
--
----------------------------------------------------------------
/dev/random says: There must be more to life than compile-and-go.
python -c "print '73746566616e2e6e616577654061746c61732d656c656b74726f6e696b2e636f6d'.decode('hex')"
^ permalink raw reply
* Re: segmentation fault (nullpointer) with git log --submodule -p
From: Duy Nguyen @ 2013-01-24 13:40 UTC (permalink / raw)
To: Stefan Näwe; +Cc: Jeff King, Armin, git@vger.kernel.org
In-Reply-To: <510124F5.9090505@atlas-elektronik.com>
On Thu, Jan 24, 2013 at 7:11 PM, Stefan Näwe
<stefan.naewe@atlas-elektronik.com> wrote:
>> Does it fail with older versions of git? If so, can you bisect?
>
> I did. My bisection told me this is the suspect:
>
> ccdc603 (parse_object: try internal cache before reading object db)
diff --git a/object.c b/object.c
index d8d09f9..6b06297 100644
--- a/object.c
+++ b/object.c
@@ -191,10 +191,15 @@ struct object *parse_object(const unsigned char *sha1)
enum object_type type;
int eaten;
const unsigned char *repl = lookup_replace_object(sha1);
- void *buffer = read_sha1_file(sha1, &type, &size);
+ void *buffer;
+ struct object *obj;
+
+ obj = lookup_object(sha1);
+ if (obj && obj->parsed)
+ return obj;
Any chance obj->parsed is 1 but ((struct commit*)obj)->buffer is NULL?
What if you change that "if" to
if (obj && obj->parsed && (obj->type != OBJ_COMMIT || ((struct commit
*)obj)->buffer))
??
Also you did not encode commits in any specific encoding, nor set
i18n.logOutputEncoding?
--
Duy
^ permalink raw reply related
* Re: segmentation fault (nullpointer) with git log --submodule -p
From: Stefan Näwe @ 2013-01-24 14:06 UTC (permalink / raw)
To: Duy Nguyen; +Cc: Jeff King, Armin, git@vger.kernel.org
In-Reply-To: <CACsJy8B9O=A26_=sv1JEYdtazsWa4khZkqpTgFSSTs_RGGPZqQ@mail.gmail.com>
Am Donnerstag, 24. Januar 2013 14:40:47 schrieb Duy Nguyen:
> On Thu, Jan 24, 2013 at 7:11 PM, Stefan Näwe
> <stefan.naewe@atlas-elektronik.com> wrote:
>>> Does it fail with older versions of git? If so, can you bisect?
>>
>> I did. My bisection told me this is the suspect:
>>
>> ccdc603 (parse_object: try internal cache before reading object db)
>
> diff --git a/object.c b/object.c
> index d8d09f9..6b06297 100644
> --- a/object.c
> +++ b/object.c
> @@ -191,10 +191,15 @@ struct object *parse_object(const unsigned char *sha1)
> enum object_type type;
> int eaten;
> const unsigned char *repl = lookup_replace_object(sha1);
> - void *buffer = read_sha1_file(sha1, &type, &size);
> + void *buffer;
> + struct object *obj;
> +
> + obj = lookup_object(sha1);
> + if (obj && obj->parsed)
> + return obj;
>
> Any chance obj->parsed is 1 but ((struct commit*)obj)->buffer is NULL?
> What if you change that "if" to
>
> if (obj && obj->parsed && (obj->type != OBJ_COMMIT || ((struct commit
> *)obj)->buffer))
>
No more segfault!
> Also you did not encode commits in any specific encoding,
We're using Git for Windows and some commits contain 'umlauts' (äöü).
But those characters should be encoded in UTF-8, shouldn't they?
But the 'git log...' only crashes on a Debian/Linux machine.
> nor set i18n.logOutputEncoding?
It's not set.
(only i18n.filesEncoding is set to utf-8 on my machine)
Oh, and it's not crashing if I do:
git log -p --submodule |cat
Stefan
--
----------------------------------------------------------------
/dev/random says: Dumb luck beats sound planning every time. Trust me.
python -c "print
'73746566616e2e6e616577654061746c61732d656c656b74726f6e696b2e636f6d'.decode('hex')"
^ permalink raw reply
* Re: segmentation fault (nullpointer) with git log --submodule -p
From: Duy Nguyen @ 2013-01-24 14:14 UTC (permalink / raw)
To: Stefan Näwe; +Cc: Jeff King, Armin, git@vger.kernel.org
In-Reply-To: <51013FDD.5030004@atlas-elektronik.com>
On Thu, Jan 24, 2013 at 9:06 PM, Stefan Näwe
<stefan.naewe@atlas-elektronik.com> wrote:
> Am Donnerstag, 24. Januar 2013 14:40:47 schrieb Duy Nguyen:
>> On Thu, Jan 24, 2013 at 7:11 PM, Stefan Näwe
>> <stefan.naewe@atlas-elektronik.com> wrote:
>>>> Does it fail with older versions of git? If so, can you bisect?
>>>
>>> I did. My bisection told me this is the suspect:
>>>
>>> ccdc603 (parse_object: try internal cache before reading object db)
>>
>> diff --git a/object.c b/object.c
>> index d8d09f9..6b06297 100644
>> --- a/object.c
>> +++ b/object.c
>> @@ -191,10 +191,15 @@ struct object *parse_object(const unsigned char *sha1)
>> enum object_type type;
>> int eaten;
>> const unsigned char *repl = lookup_replace_object(sha1);
>> - void *buffer = read_sha1_file(sha1, &type, &size);
>> + void *buffer;
>> + struct object *obj;
>> +
>> + obj = lookup_object(sha1);
>> + if (obj && obj->parsed)
>> + return obj;
>>
>> Any chance obj->parsed is 1 but ((struct commit*)obj)->buffer is NULL?
>> What if you change that "if" to
>>
>> if (obj && obj->parsed && (obj->type != OBJ_COMMIT || ((struct commit
>> *)obj)->buffer))
>>
>
> No more segfault!
Sweet. I have no idea how that fixes it. Maybe Jeff can give some
explanation after he wakes up.
--
Duy
^ permalink raw reply
* Re: [PATCH] parse_object: clear "parsed" when freeing buffers
From: Junio C Hamano @ 2013-01-24 16:51 UTC (permalink / raw)
To: Jeff King; +Cc: Jonathon Mah, git
In-Reply-To: <20130124063259.GA610@sigill.intra.peff.net>
Jeff King <peff@peff.net> writes:
> The ensure_commit_buffer function could look something like:
>
> int ensure_commit_buffer(struct commit *item)
> {
> enum object_type type;
> unsigned long size;
>
> if (!item)
> return -1;
> if (!item->object.parsed)
> return parse_commit(item);
> if (item->buffer)
> return 0;
>
> item->buffer = read_sha1_file(item->object.sha1, &type, &size);
> if (!item->buffer)
> return error("Could not read %s",
> sha1_to_hex(item->object.sha1);
> return 0;
> }
The more important issue is when to release them.
Only the subcommands that know that what they are doing do not need
to access commit->buffer and they operate solely on parsed data are
suppposed to flip the save_commit_buffer bit off to reclaim the
memory early, so new callers that violate that assumption may want
to call ensure_*, but if they did so when somebody cares about the
memory pressure enough to turn the bit off need to free the buffer
themselves after they use it. Otherwise the resulting program may
still be "correct" but we will end up keeping buffer that nobody
will use, just in case it is asked again.
^ permalink raw reply
* Re: [PATCH v4 3/3] push: introduce REJECT_FETCH_FIRST and REJECT_NEEDS_FORCE
From: Junio C Hamano @ 2013-01-24 17:19 UTC (permalink / raw)
To: Jeff King; +Cc: git, Chris Rorvick
In-Reply-To: <20130124065842.GC610@sigill.intra.peff.net>
Jeff King <peff@peff.net> writes:
> I wonder if we can reword it to explain more about why we do not have
> the object, without getting too inaccurate. Something like:
>
> Updates were rejected because the remote contains objects that you do
> not have locally. This is usually caused by another repository pushing
> to the same ref. You may want to first merge the remote changes (e.g.,
> 'git pull') before pushing again.
>
> I was also tempted to s/objects/work/, which is more vague, but is less
> jargon-y for new users who do not know how git works.
After all this is "hint", and there is a value in being more
approachable at the cost of being less accurate, over being
impenetrable to achieve perfect correctness.
> Also, how should this interact with the checkout-then-pull-then-push
> advice? We make a distinction for the non-fastforward case between HEAD
> and other refs. Should we be making the same distinction here?
Possibly, but I am not among the people who cared most about the
distinction there; with the default behaviour switching to 'simple',
that distinction will start mattering even less, I suspect.
^ permalink raw reply
* Re: [PATCH 1/2] upload-pack: avoid parsing objects during ref advertisement
From: Junio C Hamano @ 2013-01-24 17:25 UTC (permalink / raw)
To: Jeff King; +Cc: git, git-dev
In-Reply-To: <20130124075008.GA3249@sigill.intra.peff.net>
Jeff King <peff@peff.net> writes:
> And yeah, this should use lookup_unknown_object to extend the
> optimization to mark_our_ref (and avoid removing it for the
> ref-advertisement case, of course).
Thanks for sanity checking. Here is what is queued at the bottom of
the hide-refs topic.
-- >8 --
Date: Fri, 18 Jan 2013 15:48:49 -0800
Subject: [PATCH] upload-pack: share more code
We mark the objects pointed at our refs with "OUR_REF" flag in two
functions (mark_our_ref() and send_ref()), but we can just use the
former as a helper for the latter.
Update the way mark_our_ref() prepares in-core object to use
lookup_unknown_object() to delay reading the actual object data,
just like we did in 435c833 (upload-pack: use peel_ref for ref
advertisements, 2012-10-04).
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
upload-pack.c | 31 ++++++++++++++-----------------
1 file changed, 14 insertions(+), 17 deletions(-)
diff --git a/upload-pack.c b/upload-pack.c
index 95d8313..3dd220d 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -722,15 +722,28 @@ static void receive_needs(void)
free(shallows.objects);
}
+static int mark_our_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
+{
+ struct object *o = lookup_unknown_object(sha1);
+ if (!o)
+ die("git upload-pack: cannot find object %s:", sha1_to_hex(sha1));
+ if (!(o->flags & OUR_REF)) {
+ o->flags |= OUR_REF;
+ nr_our_refs++;
+ }
+ return 0;
+}
+
static int send_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
{
static const char *capabilities = "multi_ack thin-pack side-band"
" side-band-64k ofs-delta shallow no-progress"
" include-tag multi_ack_detailed";
- struct object *o = lookup_unknown_object(sha1);
const char *refname_nons = strip_namespace(refname);
unsigned char peeled[20];
+ mark_our_ref(refname, sha1, flag, cb_data);
+
if (capabilities)
packet_write(1, "%s %s%c%s%s agent=%s\n",
sha1_to_hex(sha1), refname_nons,
@@ -740,27 +753,11 @@ static int send_ref(const char *refname, const unsigned char *sha1, int flag, vo
else
packet_write(1, "%s %s\n", sha1_to_hex(sha1), refname_nons);
capabilities = NULL;
- if (!(o->flags & OUR_REF)) {
- o->flags |= OUR_REF;
- nr_our_refs++;
- }
if (!peel_ref(refname, peeled))
packet_write(1, "%s %s^{}\n", sha1_to_hex(peeled), refname_nons);
return 0;
}
-static int mark_our_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
-{
- struct object *o = parse_object(sha1);
- if (!o)
- die("git upload-pack: cannot find object %s:", sha1_to_hex(sha1));
- if (!(o->flags & OUR_REF)) {
- o->flags |= OUR_REF;
- nr_our_refs++;
- }
- return 0;
-}
-
static void upload_pack(void)
{
if (advertise_refs || !stateless_rpc) {
--
1.8.1.1.525.gdace530
^ permalink raw reply related
* Re: [PATCH 1/7] sha1_file: keep track of where an SHA-1 object comes from
From: Junio C Hamano @ 2013-01-24 17:45 UTC (permalink / raw)
To: Nguyễn Thái Ngọc Duy; +Cc: git, Jens Lehmann
In-Reply-To: <1359016940-18849-1-git-send-email-pclouds@gmail.com>
Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes:
> We currently know if an object is loose or packed. We do not know if
> it's from the repo's object database, or via alternates
> mechanism. With this patch, sha1_object_info_extended() can tell if an
> object comes from alternates source (and which one).
>
> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
> ---
> How about this way instead: we keep track of where objects come from
> so we can verify object source when we create or update something
> that contains SHA-1.
The overall approach taken by this series may be worth considering, but
I do not think the check implemented here is correct.
An object may be found in an alternate odb but we may also have our
own copy of the same object. You need to prove that a suspicious
object is visible to us *ONLY* through add_submodule_odb().
Once you do add_submodule_odb() to contaminate our object pool, you
make everything a suspicious object that needs to be checked; that
is the worst part of the story.
If I understand the test case that triggers the issue correctly, it
makes a merge in the top-level superproject, and while doing so,
tries to three-way merge gitlink changes, so that it can detect
fast-forward situation inside the submodule. It should just be done
with running "git merge-base A B" there; after all, we are in the
tree-wide merge of the top-level superproject, which is already a
heavy-weight operation. I do not see a reason to make it more brittle
than necessary.
If we rip out add_submodule_odb() we do not have to ever worry about
this kind of object database breakages that are hard to track down.
It is an optimization to allow the code become more brittle, violate
the project boundary, and break the object database faster as a
result. That is not a good optimization at all.
^ permalink raw reply
* Re: [PATCH] send-email: Honor multi-part email messages
From: Junio C Hamano @ 2013-01-24 18:11 UTC (permalink / raw)
To: Alexey Shumkin; +Cc: git
In-Reply-To: <20130124143816.7c33fc1c@ashu.dyn1.rarus.ru>
Alexey Shumkin <alex.crezoff@gmail.com> writes:
> Bump
Bump what???
^ 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