* [PATCH 13] autoconf: Append '-include config.mak.autogen' to config.mak if it is not present
From: Jakub Narebski @ 2006-06-30 15:11 UTC (permalink / raw)
To: git; +Cc: Andreas Ericsson
In-Reply-To: <200606301708.19521.jnareb@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
Andreas Ericsson wrote:
> Jakub Narebski wrote:
>>
>> The idea was to use ./configure to _generate_ config.mak, which the user can
>> then edit.
>
> This is bad, since it forces users to do one thing first and then do
> what they're used to. Better to have the script add
>
> -include config.mak.autogen
>
> LAST in config.mak, unless it's already in the file and generate
> config.mak.autogen with configure, e.g. with
>
> grep -q autogen config.mak || \
> echo "-include config.mak.autogen" >> config.mak
>
> Since Make does things bottoms-up (much like swedish students and
> midsummer celebrators), the previous hand-edited defaults in config.mak
> will beat the ones in config.mak.autogen (a good thing).
>
> I wouldn't want my long-standing, functioning config.mak overwritten,
> but I *might* be interested in trying some of the options provided by
> ./configure.
Done, with small changes.
Can anyone tell me if frep use is portable enough?
configure.ac | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/configure.ac b/configure.ac
index 1ead656..2904077 100644
--- a/configure.ac
+++ b/configure.ac
@@ -54,3 +54,6 @@ AC_CONFIG_FILES(["${config_file}":"${con
AC_OUTPUT
rm -f "${config_append}"
+
+grep -q -s -F "-include ${config_file}" config.mak || \
+ echo "-include ${config_file}" >> config.mak
--
1.4.0
^ permalink raw reply related
* [PATCH 12] Revert "autoconf: Write how to use ./configure generated file in git build process"
From: Jakub Narebski @ 2006-06-30 15:08 UTC (permalink / raw)
To: git
In-Reply-To: <200606301441.01327.jnareb@gmail.com>
This reverts 6015ccba6c0439b0b615615aacefaf463c546ba4 commit.
To be replaced by better solution, idea by Andreas Ericsson
---
Or just not apply [PATCH 10] (and this patch)
configure.ac | 6 ------
1 files changed, 0 insertions(+), 6 deletions(-)
diff --git a/configure.ac b/configure.ac
index f01fc17..1ead656 100644
--- a/configure.ac
+++ b/configure.ac
@@ -54,9 +54,3 @@ AC_CONFIG_FILES(["${config_file}":"${con
AC_OUTPUT
rm -f "${config_append}"
-
-cat <<_ACEOF
-
-Add '-include ${config_file}' to your config.mak,
-or rename ${config_file} to config.mak
-_ACEOF
--
1.4.0
^ permalink raw reply related
* [PATCH 3/3] merge-recursive: avoid the pipe to update-index
From: Johannes Schindelin @ 2006-06-30 14:44 UTC (permalink / raw)
To: Alex Riesen; +Cc: git
In-Reply-To: <Pine.LNX.4.63.0606300235300.29667@wbgn013.biozentrum.uni-wuerzburg.de>
Instead of a fork, we can use the plumbing ;-)
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
graph.c | 26 -----
merge-recursive.c | 270 +++++++++++++++++++++++++++++++++++++----------------
2 files changed, 191 insertions(+), 105 deletions(-)
diff --git a/graph.c b/graph.c
index fa2bfee..b784ea2 100644
--- a/graph.c
+++ b/graph.c
@@ -5,32 +5,6 @@ #include "cache.h"
#include "commit.h"
#include "graph.h"
-// does not belong here
-struct tree *git_write_tree()
-{
-#if 0
- fprintf(stderr, "GIT_INDEX_FILE='%s' git-write-tree\n",
- getenv("GIT_INDEX_FILE"));
-#endif
- FILE *fp = popen("git-write-tree 2>/dev/null", "r");
- char buf[41];
- unsigned char sha1[20];
- int ch;
- unsigned i = 0;
- while ( (ch = fgetc(fp)) != EOF )
- if ( i < sizeof(buf)-1 && ch >= '0' && ch <= 'f' )
- buf[i++] = ch;
- else
- break;
- int rc = pclose(fp);
- if ( rc == -1 || WEXITSTATUS(rc) )
- return NULL;
- buf[i] = '\0';
- if ( get_sha1(buf, sha1) != 0 )
- return NULL;
- return lookup_tree(sha1);
-}
-
const char *node_title(struct node *node, int *len)
{
const char *s = "(null commit)";
diff --git a/merge-recursive.c b/merge-recursive.c
index 9bbb426..6d4e797 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -9,6 +9,7 @@ #include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "cache.h"
+#include "cache-tree.h"
#include "commit.h"
#include "blob.h"
#include "tree-walk.h"
@@ -19,6 +20,47 @@ #include "run-command.h"
#include "graph.h"
#include "path-list.h"
+#ifdef DEBUG
+#include "quote.h"
+static void show_ce_entry(const char *tag, struct cache_entry *ce)
+{
+ if (tag && *tag &&
+ (ce->ce_flags & htons(CE_VALID))) {
+ static char alttag[4];
+ memcpy(alttag, tag, 3);
+ if (isalpha(tag[0]))
+ alttag[0] = tolower(tag[0]);
+ else if (tag[0] == '?')
+ alttag[0] = '!';
+ else {
+ alttag[0] = 'v';
+ alttag[1] = tag[0];
+ alttag[2] = ' ';
+ alttag[3] = 0;
+ }
+ tag = alttag;
+ }
+
+ fprintf(stderr,"%s%06o %s %d\t",
+ tag,
+ ntohl(ce->ce_mode),
+ sha1_to_hex(ce->sha1),
+ ce_stage(ce));
+ write_name_quoted("", 0, ce->name,
+ '\n', stderr);
+ fputc('\n', stderr);
+}
+
+static void ls_files() {
+ int i;
+ for (i = 0; i < active_nr; i++) {
+ struct cache_entry *ce = active_cache[i];
+ show_ce_entry("", ce);
+ }
+ fprintf(stderr, "---\n");
+}
+#endif
+
#define for_each_commit(p,list) for ( p = (list); p; p = p->next )
struct merge_result
@@ -94,12 +136,68 @@ static void output(const char *fmt, ...)
static const char *original_index_file;
static const char *temporary_index_file;
+static int cache_dirty = 0;
+
+static int flush_cache()
+{
+ /* flush temporary index */
+ struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
+ int fd = hold_lock_file_for_update(lock, getenv("GIT_INDEX_FILE"));
+ if (fd < 0)
+ die("could not lock %s", temporary_index_file);
+ if (write_cache(fd, active_cache, active_nr) ||
+ commit_lock_file(lock))
+ die ("unable to write %s", temporary_index_file);
+ discard_cache();
+ cache_dirty = 0;
+ return 0;
+}
static void setup_index(int temp)
{
const char *idx = temp ? temporary_index_file: original_index_file;
+ if (cache_dirty)
+ die("fatal: cache changed flush_cache();");
unlink(temporary_index_file);
setenv("GIT_INDEX_FILE", idx, 1);
+ discard_cache();
+}
+
+static struct cache_entry *make_cache_entry(unsigned int mode,
+ const unsigned char *sha1, const char *path, int stage, int refresh)
+{
+ int size, len;
+ struct cache_entry *ce;
+
+ if (!verify_path(path))
+ return NULL;
+
+ len = strlen(path);
+ size = cache_entry_size(len);
+ ce = xcalloc(1, size);
+
+ memcpy(ce->sha1, sha1, 20);
+ memcpy(ce->name, path, len);
+ ce->ce_flags = create_ce_flags(len, stage);
+ ce->ce_mode = create_ce_mode(mode);
+
+ if (refresh)
+ return refresh_cache_entry(ce, 0);
+
+ return ce;
+}
+
+static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,
+ const char *path, int stage, int refresh, int options)
+{
+ struct cache_entry *ce;
+ if (!cache_dirty)
+ read_cache_from(getenv("GIT_INDEX_FILE"));
+ cache_dirty++;
+ ce = make_cache_entry(mode, sha1 ? sha1 : null_sha1, path, stage, refresh);
+ if (!ce)
+ return error("cache_addinfo failed: %s", strerror(cache_errno));
+ return add_cache_entry(ce, options);
}
// This is a global variable which is used in a number of places but
@@ -119,6 +217,8 @@ #if 0
sha1_to_hex(tree->object.sha1));
#endif
const char *argv[] = { "git-read-tree", NULL, NULL, };
+ if (cache_dirty)
+ die("read-tree with dirty cache");
argv[1] = sha1_to_hex(tree->object.sha1);
int rc = run_command_v(2, argv);
return rc < 0 ? -1: rc;
@@ -141,6 +241,8 @@ #endif
"git-read-tree", NULL, "-m", NULL, NULL, NULL,
NULL,
};
+ if (cache_dirty)
+ flush_cache();
argv[1] = update_arg;
argv[3] = sha1_to_hex(common->object.sha1);
argv[4] = sha1_to_hex(head->object.sha1);
@@ -149,6 +251,33 @@ #endif
return rc < 0 ? -1: rc;
}
+struct tree *git_write_tree()
+{
+#if 0
+ fprintf(stderr, "GIT_INDEX_FILE='%s' git-write-tree\n",
+ getenv("GIT_INDEX_FILE"));
+#endif
+ if (cache_dirty)
+ flush_cache();
+ FILE *fp = popen("git-write-tree 2>/dev/null", "r");
+ char buf[41];
+ unsigned char sha1[20];
+ int ch;
+ unsigned i = 0;
+ while ( (ch = fgetc(fp)) != EOF )
+ if ( i < sizeof(buf)-1 && ch >= '0' && ch <= 'f' )
+ buf[i++] = ch;
+ else
+ break;
+ int rc = pclose(fp);
+ if ( rc == -1 || WEXITSTATUS(rc) )
+ return NULL;
+ buf[i] = '\0';
+ if ( get_sha1(buf, sha1) != 0 )
+ return NULL;
+ return lookup_tree(sha1);
+}
+
struct merge_tree_result merge_trees(struct tree *head,
struct tree *merge,
struct tree *common,
@@ -640,36 +769,25 @@ struct rename_entry *getRenames(struct t
return renames;
}
-static FILE *git_update_index_pipe()
-{
- return popen("git-update-index -z --index-info", "w");
-}
-
-int setIndexStages(FILE *fp,
- const char *path,
+int setIndexStages(const char *path,
unsigned char *osha, unsigned omode,
unsigned char *asha, unsigned amode,
unsigned char *bsha, unsigned bmode,
int clear /* =True */)
{
- if ( !fp )
- return -1;
- if ( clear ) {
- fprintf(fp, "0 %s\t%s", sha1_to_hex(null_sha1), path);
- fputc('\0', fp);
- }
- if ( omode ) {
- fprintf(fp, "0%o %s 1\t%s", omode, sha1_to_hex(osha), path);
- fputc('\0', fp);
- }
- if ( amode ) {
- fprintf(fp, "0%o %s 2\t%s", amode, sha1_to_hex(asha), path);
- fputc('\0', fp);
- }
- if ( bmode ) {
- fprintf(fp, "0%o %s 3\t%s", bmode, sha1_to_hex(bsha), path);
- fputc('\0', fp);
- }
+ int options = ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE;
+ if ( clear )
+ if (add_cacheinfo(0, null_sha1, path, 0, 0, options))
+ return -1;
+ if ( omode )
+ if (add_cacheinfo(omode, osha, path, 1, 0, options))
+ return -1;
+ if ( amode )
+ if (add_cacheinfo(omode, osha, path, 2, 0, options))
+ return -1;
+ if ( bmode )
+ if (add_cacheinfo(omode, osha, path, 3, 0, options))
+ return -1;
return 0;
}
@@ -695,17 +813,17 @@ static int remove_path(const char *name)
return ret;
}
-int removeFile(FILE *fp, int clean, const char *path)
+int removeFile(int clean, const char *path)
{
int updateCache = index_only || clean;
int updateWd = !index_only;
if ( updateCache ) {
- if ( !fp )
+ if (!cache_dirty)
+ read_cache_from(getenv("GIT_INDEX_FILE"));
+ cache_dirty++;
+ if (remove_file_from_cache(path))
return -1;
- fprintf(fp, "0 %s\t%s", sha1_to_hex(null_sha1), path);
- fputc('\0', fp);
- return 0;
}
if ( updateWd )
{
@@ -785,8 +903,7 @@ static void flush_buffer(int fd, const c
}
}
-void updateFileExt(FILE *fp,
- const unsigned char *sha,
+void updateFileExt(const unsigned char *sha,
unsigned mode,
const char *path,
int updateCache,
@@ -830,20 +947,15 @@ void updateFileExt(FILE *fp,
mode, sha1_to_hex(sha), path);
}
if ( updateCache )
- {
- // XXX just always use "git update-index --index-info"?
- fprintf(fp, "%06o %s\t%s", mode, sha1_to_hex(sha), path);
- fputc('\0', fp);
- }
+ add_cacheinfo(mode, sha, path, 0, updateWd, ADD_CACHE_OK_TO_ADD);
}
-void updateFile(FILE *fp,
- int clean,
+void updateFile(int clean,
const unsigned char *sha,
unsigned mode,
const char *path)
{
- updateFileExt(fp, sha, mode, path, index_only || clean, !index_only);
+ updateFileExt(sha, mode, path, index_only || clean, !index_only);
}
// Low level file merging, update and removal
@@ -1004,7 +1116,6 @@ int processRenames(struct rename_entry *
for (sre = renamesB; sre; sre = sre->next)
path_list_insert(sre->src, &srcNames);
- FILE *fp = git_update_index_pipe();
for_each_path(src,&srcNames) {
struct rename_entry *renames1, *renames2, *ren1, *ren2;
const char *branchName1, *branchName2;
@@ -1050,26 +1161,26 @@ int processRenames(struct rename_entry *
dstName1 = uniquePath(ren1->dst, branchName1);
output("%s is a directory in %s adding as %s instead",
ren1->dst, branchName2, dstName1);
- removeFile(fp, 0, ren1->dst);
+ removeFile(0, ren1->dst);
}
if ( path_list_has_path(¤tDirectorySet, ren2->dst) ) {
dstName2 = uniquePath(ren2->dst, branchName2);
output("%s is a directory in %s adding as %s instead",
ren2->dst, branchName1, dstName2);
- removeFile(fp, 0, ren2->dst);
+ removeFile(0, ren2->dst);
}
- setIndexStages(fp, dstName1,
+ setIndexStages(dstName1,
NULL, 0,
ren1->dst_sha, ren1->dst_mode,
NULL, 0,
1 /* clear */);
- setIndexStages(fp, dstName2,
+ setIndexStages(dstName2,
NULL, 0,
NULL, 0,
ren2->dst_sha, ren2->dst_mode,
1 /* clear */);
} else {
- removeFile(fp, 1, ren1->src);
+ removeFile(1, ren1->src);
struct merge_file_info mfi;
mfi = mergeFile(ren1->src, ren1->src_sha, ren1->src_mode,
ren1->dst, ren1->dst_sha, ren1->dst_mode,
@@ -1087,18 +1198,17 @@ int processRenames(struct rename_entry *
cleanMerge = 0;
if ( !index_only )
- setIndexStages(fp,
- ren1->dst,
+ setIndexStages(ren1->dst,
ren1->src_sha, ren1->src_mode,
ren1->dst_sha, ren1->dst_mode,
ren2->dst_sha, ren2->dst_mode,
1 /* clear */);
}
- updateFile(fp, mfi.clean, mfi.sha, mfi.mode, ren1->dst);
+ updateFile(mfi.clean, mfi.sha, mfi.mode, ren1->dst);
}
} else {
// Renamed in 1, maybe changed in 2
- removeFile(fp, 1, ren1->src);
+ removeFile(1, ren1->src);
unsigned char srcShaOtherBranch[20], dstShaOtherBranch[20];
unsigned srcModeOtherBranch, dstModeOtherBranch;
@@ -1123,15 +1233,15 @@ int processRenames(struct rename_entry *
ren1->dst, branchName2);
output("Renaming %s to %s instead", ren1->src, newPath);
cleanMerge = 0;
- removeFile(fp, 0, ren1->dst);
- updateFile(fp, 0, ren1->dst_sha, ren1->dst_mode, newPath);
+ removeFile(0, ren1->dst);
+ updateFile(0, ren1->dst_sha, ren1->dst_mode, newPath);
} else if ( memcmp(srcShaOtherBranch, null_sha1, 20) == 0 ) {
output("CONFLICT (rename/delete): Rename %s->%s in %s "
"and deleted in %s",
ren1->src, ren1->dst, branchName1,
branchName2);
cleanMerge = 0;
- updateFile(fp, 0, ren1->dst_sha, ren1->dst_mode, ren1->dst);
+ updateFile(0, ren1->dst_sha, ren1->dst_mode, ren1->dst);
} else if ( memcmp(dstShaOtherBranch, null_sha1, 20) != 0 ) {
newPath = uniquePath(ren1->dst, branchName2);
output("CONFLICT (rename/add): Rename %s->%s in %s. "
@@ -1139,7 +1249,7 @@ int processRenames(struct rename_entry *
ren1->src, ren1->dst, branchName1,
ren1->dst, branchName2);
output("Adding as %s instead", newPath);
- updateFile(fp, 0, dstShaOtherBranch, dstModeOtherBranch, newPath);
+ updateFile(0, dstShaOtherBranch, dstModeOtherBranch, newPath);
cleanMerge = 0;
tryMerge = 1;
} else if ( (dst2 = find_rename_bydst(renames2, ren1->dst)) ) {
@@ -1151,9 +1261,9 @@ int processRenames(struct rename_entry *
dst2->src, dst2->dst, branchName2);
output("Renaming %s to %s and %s to %s instead",
ren1->src, newPath1, dst2->src, newPath2);
- removeFile(fp, 0, ren1->dst);
- updateFile(fp, 0, ren1->dst_sha, ren1->dst_mode, newPath1);
- updateFile(fp, 0, dst2->dst_sha, dst2->dst_mode, newPath2);
+ removeFile(0, ren1->dst);
+ updateFile(0, ren1->dst_sha, ren1->dst_mode, newPath1);
+ updateFile(0, dst2->dst_sha, dst2->dst_mode, newPath2);
dst2->processed = 1;
cleanMerge = 0;
} else
@@ -1194,21 +1304,19 @@ int processRenames(struct rename_entry *
cleanMerge = 0;
if ( !index_only )
- setIndexStages(fp,
- ren1->dst,
+ setIndexStages(ren1->dst,
osha, omode,
asha, amode,
bsha, bmode,
1 /* clear */);
}
- updateFile(fp, mfi.clean, mfi.sha, mfi.mode, ren1->dst);
+ updateFile(mfi.clean, mfi.sha, mfi.mode, ren1->dst);
}
}
}
path_list_clear(&srcNames, 0);
- if (pclose(fp)) {
- die("git update-index --index-info failed");
- }
+ if (cache_dirty)
+ flush_cache();
return cleanMerge;
}
@@ -1241,7 +1349,6 @@ int processEntry(struct index_entry *ent
unsigned oMode = entry->stages[1].mode;
unsigned aMode = entry->stages[2].mode;
unsigned bMode = entry->stages[3].mode;
- FILE *fp = git_update_index_pipe();
if ( oSha && (!aSha || !bSha) ) {
//
@@ -1253,7 +1360,7 @@ int processEntry(struct index_entry *ent
// Deleted in both or deleted in one and unchanged in the other
if ( aSha )
output("Removing %s", path);
- removeFile(fp, 1, path);
+ removeFile(1, path);
} else {
// Deleted in one and changed in the other
cleanMerge = 0;
@@ -1262,13 +1369,13 @@ int processEntry(struct index_entry *ent
"and modified in %s. Version %s of %s left in tree.",
path, branch1Name,
branch2Name, branch2Name, path);
- updateFile(fp, 0, bSha, bMode, path);
+ updateFile(0, bSha, bMode, path);
} else {
output("CONFLICT (delete/modify): %s deleted in %s "
"and modified in %s. Version %s of %s left in tree.",
path, branch2Name,
branch1Name, branch1Name, path);
- updateFile(fp, 0, aSha, aMode, path);
+ updateFile(0, aSha, aMode, path);
}
}
@@ -1302,11 +1409,11 @@ int processEntry(struct index_entry *ent
output("CONFLICT (%s): There is a directory with name %s in %s. "
"Adding %s as %s",
conf, path, otherBranch, path, newPath);
- removeFile(fp, 0, path);
- updateFile(fp, 0, sha, mode, newPath);
+ removeFile(0, path);
+ updateFile(0, sha, mode, newPath);
} else {
output("Adding %s", path);
- updateFile(fp, 1, sha, mode, path);
+ updateFile(1, sha, mode, path);
}
} else if ( !oSha && aSha && bSha ) {
//
@@ -1319,7 +1426,7 @@ int processEntry(struct index_entry *ent
"but permissions conflict %06o->%06o",
path, aMode, bMode);
output("CONFLICT: adding with permission: %06o", aMode);
- updateFile(fp, 0, aSha, aMode, path);
+ updateFile(0, aSha, aMode, path);
} else {
// This case is handled by git-read-tree
assert(0 && "This case must be handled by git-read-tree");
@@ -1331,9 +1438,9 @@ int processEntry(struct index_entry *ent
output("CONFLICT (add/add): File %s added non-identically "
"in both branches. Adding as %s and %s instead.",
path, newPath1, newPath2);
- removeFile(fp, 0, path);
- updateFile(fp, 0, aSha, aMode, newPath1);
- updateFile(fp, 0, bSha, bMode, newPath2);
+ removeFile(0, path);
+ updateFile(0, aSha, aMode, newPath1);
+ updateFile(0, bSha, bMode, newPath2);
}
} else if ( oSha && aSha && bSha ) {
@@ -1348,22 +1455,23 @@ int processEntry(struct index_entry *ent
branch1Name, branch2Name);
if ( mfi.clean )
- updateFile(fp, 1, mfi.sha, mfi.mode, path);
+ updateFile(1, mfi.sha, mfi.mode, path);
else {
cleanMerge = 0;
output("CONFLICT (content): Merge conflict in %s", path);
if ( index_only )
- updateFile(fp, 0, mfi.sha, mfi.mode, path);
+ updateFile(0, mfi.sha, mfi.mode, path);
else
- updateFileExt(fp, mfi.sha, mfi.mode, path,
+ updateFileExt(mfi.sha, mfi.mode, path,
0 /* updateCache */, 1 /* updateWd */);
}
} else
die("Fatal merge failure, shouldn't happen.");
- if (pclose(fp))
- die("updating entry failed in git update-index");
+ if (cache_dirty)
+ flush_cache();
+
return cleanMerge;
}
@@ -1570,6 +1678,10 @@ int main(int argc, char *argv[])
struct graph *graph = graph_build(commits);
result = merge(h1, h2, branch1, branch2, graph, 0, NULL);
}
+
+ if (cache_dirty)
+ flush_cache();
+
return result.clean ? 0: 1;
}
--
1.4.1.rc1.gb2d14
^ permalink raw reply related
* [PATCH 2/3] Make refresh_cache_entry() public
From: Johannes Schindelin @ 2006-06-30 14:43 UTC (permalink / raw)
To: Alex Riesen; +Cc: git
In-Reply-To: <Pine.LNX.4.63.0606300235300.29667@wbgn013.biozentrum.uni-wuerzburg.de>
This renames refresh_entry() to refresh_cache_entry(), to make clashes
more unlikely, and makes it public. It also rethinks the rather awkward
way to pass an error: this is done by returning a NULL pointer and setting
cache_errno now.
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
---
cache.h | 2 ++
read-cache.c | 44 +++++++++++++++++---------------------------
2 files changed, 19 insertions(+), 27 deletions(-)
diff --git a/cache.h b/cache.h
index a5343db..a59b319 100644
--- a/cache.h
+++ b/cache.h
@@ -115,6 +115,7 @@ #define cache_entry_size(len) ((offsetof
extern struct cache_entry **active_cache;
extern unsigned int active_nr, active_alloc, active_cache_changed;
extern struct cache_tree *active_cache_tree;
+extern int cache_errno;
#define GIT_DIR_ENVIRONMENT "GIT_DIR"
#define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
@@ -151,6 +152,7 @@ #define ADD_CACHE_OK_TO_ADD 1 /* Ok to
#define ADD_CACHE_OK_TO_REPLACE 2 /* Ok to replace file/directory */
#define ADD_CACHE_SKIP_DFCHECK 4 /* Ok to skip DF conflict checks */
extern int add_cache_entry(struct cache_entry *ce, int option);
+extern struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really);
extern int remove_cache_entry_at(int pos);
extern int remove_file_from_cache(const char *path);
extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);
diff --git a/read-cache.c b/read-cache.c
index 04d2ec7..1c0fc8b 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -24,6 +24,8 @@ unsigned int active_nr = 0, active_alloc
struct cache_tree *active_cache_tree = NULL;
+int cache_errno = 0;
+
static void *cache_mmap = NULL;
static size_t cache_mmap_size = 0;
@@ -580,22 +582,6 @@ int add_cache_entry(struct cache_entry *
return 0;
}
-/* Three functions to allow overloaded pointer return; see linux/err.h */
-static inline void *ERR_PTR(long error)
-{
- return (void *) error;
-}
-
-static inline long PTR_ERR(const void *ptr)
-{
- return (long) ptr;
-}
-
-static inline long IS_ERR(const void *ptr)
-{
- return (unsigned long)ptr > (unsigned long)-1000L;
-}
-
/*
* "refresh" does not calculate a new sha1 file or bring the
* cache up-to-date for mode/content changes. But what it
@@ -607,14 +593,16 @@ static inline long IS_ERR(const void *pt
* For example, you'd want to do this after doing a "git-read-tree",
* to link up the stat cache details with the proper files.
*/
-static struct cache_entry *refresh_entry(struct cache_entry *ce, int really)
+struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really)
{
struct stat st;
struct cache_entry *updated;
int changed, size;
- if (lstat(ce->name, &st) < 0)
- return ERR_PTR(-errno);
+ if (lstat(ce->name, &st) < 0) {
+ cache_errno = errno;
+ return NULL;
+ }
changed = ce_match_stat(ce, &st, really);
if (!changed) {
@@ -622,11 +610,13 @@ static struct cache_entry *refresh_entry
!(ce->ce_flags & htons(CE_VALID)))
; /* mark this one VALID again */
else
- return NULL;
+ return ce;
}
- if (ce_modified(ce, &st, really))
- return ERR_PTR(-EINVAL);
+ if (ce_modified(ce, &st, really)) {
+ cache_errno = EINVAL;
+ return NULL;
+ }
size = ce_size(ce);
updated = xmalloc(size);
@@ -669,13 +659,13 @@ int refresh_cache(unsigned int flags)
continue;
}
- new = refresh_entry(ce, really);
- if (!new)
+ new = refresh_cache_entry(ce, really);
+ if (new == ce)
continue;
- if (IS_ERR(new)) {
- if (not_new && PTR_ERR(new) == -ENOENT)
+ if (!new) {
+ if (not_new && cache_errno == ENOENT)
continue;
- if (really && PTR_ERR(new) == -EINVAL) {
+ if (really && cache_errno == EINVAL) {
/* If we are doing --really-refresh that
* means the index is not valid anymore.
*/
--
1.4.1.rc1.gb2d14
^ permalink raw reply related
* [PATCH 1/3] Add read_cache_from() and discard_cache()
From: Johannes Schindelin @ 2006-06-30 14:43 UTC (permalink / raw)
To: Alex Riesen; +Cc: git
In-Reply-To: <Pine.LNX.4.63.0606300235300.29667@wbgn013.biozentrum.uni-wuerzburg.de>
These functions will be useful for the inbuilt merge-recursive.
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
---
cache.h | 2 ++
read-cache.c | 57 +++++++++++++++++++++++++++++++++++++++------------------
2 files changed, 41 insertions(+), 18 deletions(-)
diff --git a/cache.h b/cache.h
index 8719939..a5343db 100644
--- a/cache.h
+++ b/cache.h
@@ -142,7 +142,9 @@ #define alloc_nr(x) (((x)+16)*3/2)
/* Initialize and use the cache information */
extern int read_cache(void);
+extern int read_cache_from(const char *path);
extern int write_cache(int newfd, struct cache_entry **cache, int entries);
+extern int discard_cache(void);
extern int verify_path(const char *path);
extern int cache_name_pos(const char *name, int namelen);
#define ADD_CACHE_OK_TO_ADD 1 /* Ok to add */
diff --git a/read-cache.c b/read-cache.c
index 3c32aae..04d2ec7 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -24,6 +24,9 @@ unsigned int active_nr = 0, active_alloc
struct cache_tree *active_cache_tree = NULL;
+static void *cache_mmap = NULL;
+static size_t cache_mmap_size = 0;
+
/*
* This only updates the "non-critical" parts of the directory
* cache, ie the parts that aren't tracked by GIT, and only used
@@ -729,39 +732,43 @@ static int read_index_extension(const ch
int read_cache(void)
{
+ return read_cache_from(get_index_file());
+}
+
+/* remember to discard_cache() before reading a different cache! */
+int read_cache_from(const char *path)
+{
int fd, i;
struct stat st;
- unsigned long size, offset;
- void *map;
+ unsigned long offset;
struct cache_header *hdr;
errno = EBUSY;
- if (active_cache)
+ if (cache_mmap)
return active_nr;
errno = ENOENT;
index_file_timestamp = 0;
- fd = open(get_index_file(), O_RDONLY);
+ fd = open(path, O_RDONLY);
if (fd < 0) {
if (errno == ENOENT)
return 0;
die("index file open failed (%s)", strerror(errno));
}
- size = 0; // avoid gcc warning
- map = MAP_FAILED;
+ cache_mmap = MAP_FAILED;
if (!fstat(fd, &st)) {
- size = st.st_size;
+ cache_mmap_size = st.st_size;
errno = EINVAL;
- if (size >= sizeof(struct cache_header) + 20)
- map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+ if (cache_mmap_size >= sizeof(struct cache_header) + 20)
+ cache_mmap = mmap(NULL, cache_mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
}
close(fd);
- if (map == MAP_FAILED)
+ if (cache_mmap == MAP_FAILED)
die("index file mmap failed (%s)", strerror(errno));
- hdr = map;
- if (verify_hdr(hdr, size) < 0)
+ hdr = cache_mmap;
+ if (verify_hdr(hdr, cache_mmap_size) < 0)
goto unmap;
active_nr = ntohl(hdr->hdr_entries);
@@ -770,12 +777,12 @@ int read_cache(void)
offset = sizeof(*hdr);
for (i = 0; i < active_nr; i++) {
- struct cache_entry *ce = (struct cache_entry *) ((char *) map + offset);
+ struct cache_entry *ce = (struct cache_entry *) ((char *) cache_mmap + offset);
offset = offset + ce_size(ce);
active_cache[i] = ce;
}
index_file_timestamp = st.st_mtime;
- while (offset <= size - 20 - 8) {
+ while (offset <= cache_mmap_size - 20 - 8) {
/* After an array of active_nr index entries,
* there can be arbitrary number of extended
* sections, each of which is prefixed with
@@ -783,10 +790,10 @@ int read_cache(void)
* in 4-byte network byte order.
*/
unsigned long extsize;
- memcpy(&extsize, (char *) map + offset + 4, 4);
+ memcpy(&extsize, (char *) cache_mmap + offset + 4, 4);
extsize = ntohl(extsize);
- if (read_index_extension(((const char *) map) + offset,
- (char *) map + offset + 8,
+ if (read_index_extension(((const char *) cache_mmap) + offset,
+ (char *) cache_mmap + offset + 8,
extsize) < 0)
goto unmap;
offset += 8;
@@ -795,11 +802,25 @@ int read_cache(void)
return active_nr;
unmap:
- munmap(map, size);
+ munmap(cache_mmap, cache_mmap_size);
errno = EINVAL;
die("index file corrupt");
}
+int discard_cache()
+{
+ int ret;
+
+ if (cache_mmap == NULL)
+ return 0;
+ ret = munmap(cache_mmap, cache_mmap_size);
+ cache_mmap = NULL;
+ cache_mmap_size = 0;
+ active_nr = active_cache_changed = 0;
+ /* no need to throw away allocated active_cache */
+ return ret;
+}
+
#define WRITE_BUFFER_SIZE 8192
static unsigned char write_buffer[WRITE_BUFFER_SIZE];
static unsigned long write_buffer_len;
--
1.4.1.rc1.gb2d14
^ permalink raw reply related
* Re: [PATCH 4/4] save another call to git-update-index
From: Johannes Schindelin @ 2006-06-30 14:43 UTC (permalink / raw)
To: Alex Riesen; +Cc: git
In-Reply-To: <Pine.LNX.4.63.0606300235300.29667@wbgn013.biozentrum.uni-wuerzburg.de>
Hi,
On Fri, 30 Jun 2006, Johannes Schindelin wrote:
> FYI I've been just battling this pipe for a couple of hours. The first
> steps were easy, but since I wanted to do it incrementally, the index has
> to be written every so often, and I seem not to be able to get that right.
I just finished it. See my upcoming series of three patches. These apply
on top of your last cumulative patch (sometimes yesterday), although I am
certain we can merge our efforts.
Ciao,
Dscho
^ permalink raw reply
* [PATCH 11] autoconf: Rename ./configure output file to config.mak.autogen
From: Jakub Narebski @ 2006-06-30 12:41 UTC (permalink / raw)
To: git
In-Reply-To: <200606301439.40584.jnareb@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
Choose the name you are more comfortable with
configure.ac | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/configure.ac b/configure.ac
index ef310ee..f01fc17 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,7 +6,7 @@ AC_INIT([git], [1.4.0], [git@vger.kernel
AC_CONFIG_SRCDIR([git.c])
-config_file=config.mak.auto
+config_file=config.mak.autogen
config_append=config.mak.append
config_in=config.mak.in
--
1.4.0
^ permalink raw reply related
* [PATCH 10] autoconf: Write how to use ./configure generated file in git build process
From: Jakub Narebski @ 2006-06-30 12:39 UTC (permalink / raw)
To: git
In-Reply-To: <200606301437.52590.jnareb@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
Probably there is better way to do this.
configure.ac | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/configure.ac b/configure.ac
index e387f5b..ef310ee 100644
--- a/configure.ac
+++ b/configure.ac
@@ -54,3 +54,9 @@ AC_CONFIG_FILES(["${config_file}":"${con
AC_OUTPUT
rm -f "${config_append}"
+
+cat <<_ACEOF
+
+Add '-include ${config_file}' to your config.mak,
+or rename ${config_file} to config.mak
+_ACEOF
--
1.4.0
^ permalink raw reply related
* [PATCH 9] autoconf: Cleanup generation of temporary "append" file
From: Jakub Narebski @ 2006-06-30 12:37 UTC (permalink / raw)
To: git
In-Reply-To: <200606300232.34472.jnareb@gmail.com>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
configure.ac | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/configure.ac b/configure.ac
index 799bc87..e387f5b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -10,7 +10,7 @@ config_file=config.mak.auto
config_append=config.mak.append
config_in=config.mak.in
-echo "# ${config_append}. Generated by configure." >> "${config_append}"
+echo "# ${config_append}. Generated by configure." > "${config_append}"
# Definitions of macros
# MY_APPEND_LINE(LINE)
@@ -50,6 +50,7 @@ AC_CHECK_FUNC(setenv,,MY_APPEND_LINE(NO_
# Output files
-AC_CONFIG_FILES(["${config_file}":"${config_in}":"${config_append}"],
-[rm -f "${config_append}"])
+AC_CONFIG_FILES(["${config_file}":"${config_in}":"${config_append}"])
AC_OUTPUT
+
+rm -f "${config_append}"
--
1.4.0
^ permalink raw reply related
* Re: [PATCH] consider previous pack undeltified object state only when reusing delta data
From: Andreas Ericsson @ 2006-06-30 12:28 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Nicolas Pitre, Junio C Hamano, git
In-Reply-To: <Pine.LNX.4.63.0606301144450.29667@wbgn013.biozentrum.uni-wuerzburg.de>
Johannes Schindelin wrote:
> Hi,
>
> On Thu, 29 Jun 2006, Nicolas Pitre wrote:
>
>
>>Without this there would never be a chance to improve packing for
>>previously undeltified objects.
>
>
> Earlier this year, I was quite surprised to learn that multiple repackings
> actually improved packing. Does that patch mean this feature is gone?
>
The patch Linus sent removes that feature. This one re-introduces it.
--
Andreas Ericsson andreas.ericsson@op5.se
OP5 AB www.op5.se
Tel: +46 8-230225 Fax: +46 8-230231
^ permalink raw reply
* Re: [PATCH] autoconf: Use autoconf to write installation directories to config.mak
From: Andreas Ericsson @ 2006-06-30 12:18 UTC (permalink / raw)
To: Jakub Narebski; +Cc: git
In-Reply-To: <e80lnq$9mi$1@sea.gmane.org>
Jakub Narebski wrote:
> Matthias Lederhofer wrote:
>
>
>>>This is beginning of patch series introducing installation configuration
>>>using autoconf (and no other autotools) to git. The idea is to generate
>>>config.mak using ./configure (generated from configure.ac) from
>>>config.mak.in, so one can use autoconf as an _alternative_ to ordinary
>>>Makefile, and creating one's own config.mak.
>>
>>Are you sure this should be named config.mak? From INSTALL:
>>
>>>You can place local settings in config.mak and the Makefile
>>>will include them. Note that config.mak is not distributed;
>>>the name is reserved for local settings.
>>
>>So with another filename either include it
>>- before config.mak: the user may override ./configure options with
>> config.mak
>>- after config.mak: ./configure overrides config.mak
>
>
> The idea was to use ./configure to _generate_ config.mak, which the user can
> then edit.
>
This is bad, since it forces users to do one thing first and then do
what they're used to. Better to have the script add
-include config.mak.autogen
LAST in config.mak, unless it's already in the file and generate
config.mak.autogen with configure.
Since Make does things bottoms-up (much like swedish students and
midsummer celebrators), the previous hand-edited defaults in config.mak
will beat the ones in config.mak.autogen (a good thing).
> But perhaps using another filename for results of ./configure script
> (and including it in main Makefile) would be better idea.
>
>
>>At least do not overwrite config.mak if it exists.
>
>
> But one might want to run ./configure with different options, to finally
> arrive at the set which is satisfactionary. So unless some magic to detect
> if config.mak was generated from ./configure script, or generated by user
> is used...
>
grep -q autogen config.mak || \
echo "-include config.mak.autogen" >> config.mak
I wouldn't want my long-standing, functioning config.mak overwritten,
but I *might* be interested in trying some of the options provided by
./configure.
--
Andreas Ericsson andreas.ericsson@op5.se
OP5 AB www.op5.se
Tel: +46 8-230225 Fax: +46 8-230231
^ permalink raw reply
* Re: [PATCH 4/4] save another call to git-update-index
From: Alex Riesen @ 2006-06-30 11:33 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Alex Riesen, git
In-Reply-To: <Pine.LNX.4.63.0606301155050.29667@wbgn013.biozentrum.uni-wuerzburg.de>
On 6/30/06, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> > >
> > > FYI I've been just battling this pipe for a couple of hours. The first
> > > steps were easy, but since I wanted to do it incrementally, the index has
> > > to be written every so often, and I seem not to be able to get that right.
> > >
> > Are you sure? Does something use the index between starting update-index
> > pipe and pclose?
>
> Yes, I am sure you have to write the cache before git-read-tree and
> git-write-tree ;-)
Indeed :) That's what pclose before git-write-tree is for (which was not the
case as I published this optimization. Noticed it later. The last patch series
has pclose before git-write-tree)
> I must have done something severely wrong, though,
> since there are not too many places where they are called. The problem is
> more likely that the cache has to be _read_, and _before_ the first
> substituted call to git-update-index.
git-write-tree change index?
^ permalink raw reply
* Re: [PATCH] git-grep: --and to combine patterns with and instead of or
From: Matthias Lederhofer @ 2006-06-30 10:57 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7v3bdnkrfb.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano wrote:
> I see you are trying hard to think of a way to justify your
> original prefix "--and" (or --FOO) implementation, but I simply
> do not see much point in that. I doubt changing the default
> operator from --or to --and is less confusing than changing the
> precedence for the users, so you would hear the same "I
> personally feel FOO should not even exist" objection from me.
It just happens to make more sense to me and I don't see a reason not to
add this. If no one else is interested in this I'll just stop arguing :)
Here again an overview of the arguments if anyone is interested:
- Less to type for common searches using only AND (or more ANDs than
ORs).
- Easy to implement (both with and without extended expressions).
- AND/* is the normal implicit operator in other contexts than grep
(math).
- The high precedence operator (AND) should be implicit rather than
the low precedence one (OR) (so this is only fulfilled when the
option is used).
^ permalink raw reply
* Re: [PATCH] git-grep: boolean expression on pattern matching.
From: Junio C Hamano @ 2006-06-30 10:29 UTC (permalink / raw)
To: Jakub Narebski; +Cc: git
In-Reply-To: <e82u4l$fvb$1@sea.gmane.org>
Jakub Narebski <jnareb@gmail.com> writes:
>>
>> $ git grep -e _PATTERN --and \( -e atom -e token \)
>
> And where is documentation update?
Heh, real men do not do documentation ;-).
I am going to bed now, and am hoping a kind soul would be
sending out a patch while I am sleeping.
^ permalink raw reply
* Re: GIt.xs merge status
From: Junio C Hamano @ 2006-06-30 10:26 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.63.0606301150250.29667@wbgn013.biozentrum.uni-wuerzburg.de>
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> I'll try it (it's in pu, right?). Note that breaking git-fmt-merge-msg
> might be a good way to force somebody to rewrite it in C ;-)
It would hopefully not come to that (and that is I am playing
safe and keeping the series in "pu"), and even if it did, I am
hoping that Perl is so ubiquitous that people would fix it up
quickly.
^ permalink raw reply
* Re: [PATCH] git-grep: boolean expression on pattern matching.
From: Jakub Narebski @ 2006-06-30 10:24 UTC (permalink / raw)
To: git
In-Reply-To: <7vsllnj6rh.fsf_-_@assigned-by-dhcp.cox.net>
Junio C Hamano wrote:
> This extends the behaviour of git-grep when multiple -e options
> are given. So far, we allowed multiple -e to behave just like
> regular grep with multiple -e, i.e. the patterns are OR'ed
> together.
>
> With this change, you can also have multiple patterns AND'ed
> together, or form boolean expressions, like this (the
> parentheses are quoted from the shell in this example):
>
> $ git grep -e _PATTERN --and \( -e atom -e token \)
And where is documentation update?
--
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
^ permalink raw reply
* [PATCH] git-grep: boolean expression on pattern matching.
From: Junio C Hamano @ 2006-06-30 10:08 UTC (permalink / raw)
To: Matthias Lederhofer; +Cc: git
In-Reply-To: <7v3bdnkrfb.fsf@assigned-by-dhcp.cox.net>
This extends the behaviour of git-grep when multiple -e options
are given. So far, we allowed multiple -e to behave just like
regular grep with multiple -e, i.e. the patterns are OR'ed
together.
With this change, you can also have multiple patterns AND'ed
together, or form boolean expressions, like this (the
parentheses are quoted from the shell in this example):
$ git grep -e _PATTERN --and \( -e atom -e token \)
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
* OR'ing together, admittably, can be done easily by saying
something like -e 'atom\|token', so being able to say --and
as you argued is of more practical importance, and doing
boolean expression like this might be too much frill.
Only very lightly tested; it is obviously not slated for
1.4.1.
builtin-grep.c | 378 ++++++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 327 insertions(+), 51 deletions(-)
diff --git a/builtin-grep.c b/builtin-grep.c
index 2e7986c..70b1fd2 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -82,17 +82,47 @@ static int pathspec_matches(const char *
return 0;
}
+enum grep_pat_token {
+ GREP_PATTERN,
+ GREP_AND,
+ GREP_OPEN_PAREN,
+ GREP_CLOSE_PAREN,
+ GREP_NOT,
+ GREP_OR,
+};
+
struct grep_pat {
struct grep_pat *next;
const char *origin;
int no;
+ enum grep_pat_token token;
const char *pattern;
regex_t regexp;
};
+enum grep_expr_node {
+ GREP_NODE_ATOM,
+ GREP_NODE_NOT,
+ GREP_NODE_AND,
+ GREP_NODE_OR,
+};
+
+struct grep_expr {
+ enum grep_expr_node node;
+ union {
+ struct grep_pat *atom;
+ struct grep_expr *unary;
+ struct {
+ struct grep_expr *left;
+ struct grep_expr *right;
+ } binary;
+ } u;
+};
+
struct grep_opt {
struct grep_pat *pattern_list;
struct grep_pat **pattern_tail;
+ struct grep_expr *pattern_expression;
regex_t regexp;
unsigned linenum:1;
unsigned invert:1;
@@ -105,43 +135,224 @@ #define GREP_BINARY_DEFAULT 0
#define GREP_BINARY_NOMATCH 1
#define GREP_BINARY_TEXT 2
unsigned binary:2;
+ unsigned extended:1;
int regflags;
unsigned pre_context;
unsigned post_context;
};
static void add_pattern(struct grep_opt *opt, const char *pat,
- const char *origin, int no)
+ const char *origin, int no, enum grep_pat_token t)
{
struct grep_pat *p = xcalloc(1, sizeof(*p));
p->pattern = pat;
p->origin = origin;
p->no = no;
+ p->token = t;
*opt->pattern_tail = p;
opt->pattern_tail = &p->next;
p->next = NULL;
}
+static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
+{
+ int err = regcomp(&p->regexp, p->pattern, opt->regflags);
+ if (err) {
+ char errbuf[1024];
+ char where[1024];
+ if (p->no)
+ sprintf(where, "In '%s' at %d, ",
+ p->origin, p->no);
+ else if (p->origin)
+ sprintf(where, "%s, ", p->origin);
+ else
+ where[0] = 0;
+ regerror(err, &p->regexp, errbuf, 1024);
+ regfree(&p->regexp);
+ die("%s'%s': %s", where, p->pattern, errbuf);
+ }
+}
+
+#if DEBUG
+static inline void indent(int in)
+{
+ int i;
+ for (i = 0; i < in; i++) putchar(' ');
+}
+
+static void dump_pattern_exp(struct grep_expr *x, int in)
+{
+ switch (x->node) {
+ case GREP_NODE_ATOM:
+ indent(in);
+ puts(x->u.atom->pattern);
+ break;
+ case GREP_NODE_NOT:
+ indent(in);
+ puts("--not");
+ dump_pattern_exp(x->u.unary, in+1);
+ break;
+ case GREP_NODE_AND:
+ dump_pattern_exp(x->u.binary.left, in+1);
+ indent(in);
+ puts("--and");
+ dump_pattern_exp(x->u.binary.right, in+1);
+ break;
+ case GREP_NODE_OR:
+ dump_pattern_exp(x->u.binary.left, in+1);
+ indent(in);
+ puts("--or");
+ dump_pattern_exp(x->u.binary.right, in+1);
+ break;
+ }
+}
+
+static void looking_at(const char *msg, struct grep_pat **list)
+{
+ struct grep_pat *p = *list;
+ fprintf(stderr, "%s: looking at ", msg);
+ if (!p)
+ fprintf(stderr, "empty\n");
+ else
+ fprintf(stderr, "<%s>\n", p->pattern);
+}
+#else
+#define looking_at(a,b) do {} while(0)
+#endif
+
+static struct grep_expr *compile_pattern_expr(struct grep_pat **);
+static struct grep_expr *compile_pattern_atom(struct grep_pat **list)
+{
+ struct grep_pat *p;
+ struct grep_expr *x;
+
+ looking_at("atom", list);
+
+ p = *list;
+ switch (p->token) {
+ case GREP_PATTERN: /* atom */
+ x = xcalloc(1, sizeof (struct grep_expr));
+ x->node = GREP_NODE_ATOM;
+ x->u.atom = p;
+ *list = p->next;
+ return x;
+ case GREP_OPEN_PAREN:
+ *list = p->next;
+ x = compile_pattern_expr(list);
+ if (!x)
+ return NULL;
+ if (!*list || (*list)->token != GREP_CLOSE_PAREN)
+ die("unmatched parenthesis");
+ *list = (*list)->next;
+ return x;
+ default:
+ return NULL;
+ }
+}
+
+static struct grep_expr *compile_pattern_not(struct grep_pat **list)
+{
+ struct grep_pat *p;
+ struct grep_expr *x;
+
+ looking_at("not", list);
+
+ p = *list;
+ switch (p->token) {
+ case GREP_NOT:
+ if (!p->next)
+ die("--not not followed by pattern expression");
+ *list = p->next;
+ x = xcalloc(1, sizeof (struct grep_expr));
+ x->node = GREP_NODE_NOT;
+ x->u.unary = compile_pattern_not(list);
+ if (!x->u.unary)
+ die("--not followed by non pattern expression");
+ return x;
+ default:
+ return compile_pattern_atom(list);
+ }
+}
+
+static struct grep_expr *compile_pattern_and(struct grep_pat **list)
+{
+ struct grep_pat *p;
+ struct grep_expr *x, *y, *z;
+
+ looking_at("and", list);
+
+ x = compile_pattern_not(list);
+ p = *list;
+ if (p && p->token == GREP_AND) {
+ if (!p->next)
+ die("--and not followed by pattern expression");
+ *list = p->next;
+ y = compile_pattern_and(list);
+ if (!y)
+ die("--and not followed by pattern expression");
+ z = xcalloc(1, sizeof (struct grep_expr));
+ z->node = GREP_NODE_AND;
+ z->u.binary.left = x;
+ z->u.binary.right = y;
+ return z;
+ }
+ return x;
+}
+
+static struct grep_expr *compile_pattern_or(struct grep_pat **list)
+{
+ struct grep_pat *p;
+ struct grep_expr *x, *y, *z;
+
+ looking_at("or", list);
+
+ x = compile_pattern_and(list);
+ p = *list;
+ if (x && p && p->token != GREP_CLOSE_PAREN) {
+ y = compile_pattern_or(list);
+ if (!y)
+ die("not a pattern expression %s", p->pattern);
+ z = xcalloc(1, sizeof (struct grep_expr));
+ z->node = GREP_NODE_OR;
+ z->u.binary.left = x;
+ z->u.binary.right = y;
+ return z;
+ }
+ return x;
+}
+
+static struct grep_expr *compile_pattern_expr(struct grep_pat **list)
+{
+ looking_at("expr", list);
+
+ return compile_pattern_or(list);
+}
+
static void compile_patterns(struct grep_opt *opt)
{
struct grep_pat *p;
+
+ /* First compile regexps */
for (p = opt->pattern_list; p; p = p->next) {
- int err = regcomp(&p->regexp, p->pattern, opt->regflags);
- if (err) {
- char errbuf[1024];
- char where[1024];
- if (p->no)
- sprintf(where, "In '%s' at %d, ",
- p->origin, p->no);
- else if (p->origin)
- sprintf(where, "%s, ", p->origin);
- else
- where[0] = 0;
- regerror(err, &p->regexp, errbuf, 1024);
- regfree(&p->regexp);
- die("%s'%s': %s", where, p->pattern, errbuf);
- }
+ if (p->token == GREP_PATTERN)
+ compile_regexp(p, opt);
+ else
+ opt->extended = 1;
}
+
+ if (!opt->extended)
+ return;
+
+ /* Then bundle them up in an expression.
+ * A classic recursive descent parser would do.
+ */
+ p = opt->pattern_list;
+ opt->pattern_expression = compile_pattern_expr(&p);
+#if DEBUG
+ dump_pattern_exp(opt->pattern_expression, 0);
+#endif
+ if (p)
+ die("incomplete pattern expression: %s", p->pattern);
}
static char *end_of_line(char *cp, unsigned long *left)
@@ -196,6 +407,79 @@ static int fixmatch(const char *pattern,
}
}
+static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol, char *eol)
+{
+ int hit = 0;
+ regmatch_t pmatch[10];
+
+ if (!opt->fixed) {
+ regex_t *exp = &p->regexp;
+ hit = !regexec(exp, bol, ARRAY_SIZE(pmatch),
+ pmatch, 0);
+ }
+ else {
+ hit = !fixmatch(p->pattern, bol, pmatch);
+ }
+
+ if (hit && opt->word_regexp) {
+ /* Match beginning must be either
+ * beginning of the line, or at word
+ * boundary (i.e. the last char must
+ * not be alnum or underscore).
+ */
+ if ((pmatch[0].rm_so < 0) ||
+ (eol - bol) <= pmatch[0].rm_so ||
+ (pmatch[0].rm_eo < 0) ||
+ (eol - bol) < pmatch[0].rm_eo)
+ die("regexp returned nonsense");
+ if (pmatch[0].rm_so != 0 &&
+ word_char(bol[pmatch[0].rm_so-1]))
+ hit = 0;
+ if (pmatch[0].rm_eo != (eol-bol) &&
+ word_char(bol[pmatch[0].rm_eo]))
+ hit = 0;
+ }
+ return hit;
+}
+
+static int match_expr_eval(struct grep_opt *opt,
+ struct grep_expr *x,
+ char *bol, char *eol)
+{
+ switch (x->node) {
+ case GREP_NODE_ATOM:
+ return match_one_pattern(opt, x->u.atom, bol, eol);
+ break;
+ case GREP_NODE_NOT:
+ return !match_expr_eval(opt, x->u.unary, bol, eol);
+ case GREP_NODE_AND:
+ return (match_expr_eval(opt, x->u.binary.left, bol, eol) &&
+ match_expr_eval(opt, x->u.binary.right, bol, eol));
+ case GREP_NODE_OR:
+ return (match_expr_eval(opt, x->u.binary.left, bol, eol) ||
+ match_expr_eval(opt, x->u.binary.right, bol, eol));
+ }
+ die("Unexpected node type (internal error) %d\n", x->node);
+}
+
+static int match_expr(struct grep_opt *opt, char *bol, char *eol)
+{
+ struct grep_expr *x = opt->pattern_expression;
+ return match_expr_eval(opt, x, bol, eol);
+}
+
+static int match_line(struct grep_opt *opt, char *bol, char *eol)
+{
+ struct grep_pat *p;
+ if (opt->extended)
+ return match_expr(opt, bol, eol);
+ for (p = opt->pattern_list; p; p = p->next) {
+ if (match_one_pattern(opt, p, bol, eol))
+ return 1;
+ }
+ return 0;
+}
+
static int grep_buffer(struct grep_opt *opt, const char *name,
char *buf, unsigned long size)
{
@@ -231,46 +515,15 @@ static int grep_buffer(struct grep_opt *
hunk_mark = "--\n";
while (left) {
- regmatch_t pmatch[10];
char *eol, ch;
int hit = 0;
- struct grep_pat *p;
eol = end_of_line(bol, &left);
ch = *eol;
*eol = 0;
- for (p = opt->pattern_list; p; p = p->next) {
- if (!opt->fixed) {
- regex_t *exp = &p->regexp;
- hit = !regexec(exp, bol, ARRAY_SIZE(pmatch),
- pmatch, 0);
- }
- else {
- hit = !fixmatch(p->pattern, bol, pmatch);
- }
+ hit = match_line(opt, bol, eol);
- if (hit && opt->word_regexp) {
- /* Match beginning must be either
- * beginning of the line, or at word
- * boundary (i.e. the last char must
- * not be alnum or underscore).
- */
- if ((pmatch[0].rm_so < 0) ||
- (eol - bol) <= pmatch[0].rm_so ||
- (pmatch[0].rm_eo < 0) ||
- (eol - bol) < pmatch[0].rm_eo)
- die("regexp returned nonsense");
- if (pmatch[0].rm_so != 0 &&
- word_char(bol[pmatch[0].rm_so-1]))
- hit = 0;
- if (pmatch[0].rm_eo != (eol-bol) &&
- word_char(bol[pmatch[0].rm_eo]))
- hit = 0;
- }
- if (hit)
- break;
- }
/* "grep -v -e foo -e bla" should list lines
* that do not have either, so inversion should
* be done outside.
@@ -452,6 +705,8 @@ static int external_grep(struct grep_opt
char *argptr = randarg;
struct grep_pat *p;
+ if (opt->extended)
+ return -1;
len = nr = 0;
push_arg("grep");
if (opt->fixed)
@@ -801,16 +1056,36 @@ int cmd_grep(int argc, const char **argv
/* ignore empty line like grep does */
if (!buf[0])
continue;
- add_pattern(&opt, strdup(buf), argv[1], ++lno);
+ add_pattern(&opt, strdup(buf), argv[1], ++lno,
+ GREP_PATTERN);
}
fclose(patterns);
argv++;
argc--;
continue;
}
+ if (!strcmp("--not", arg)) {
+ add_pattern(&opt, arg, "command line", 0, GREP_NOT);
+ continue;
+ }
+ if (!strcmp("--and", arg)) {
+ add_pattern(&opt, arg, "command line", 0, GREP_AND);
+ continue;
+ }
+ if (!strcmp("--or", arg))
+ continue; /* no-op */
+ if (!strcmp("(", arg)) {
+ add_pattern(&opt, arg, "command line", 0, GREP_OPEN_PAREN);
+ continue;
+ }
+ if (!strcmp(")", arg)) {
+ add_pattern(&opt, arg, "command line", 0, GREP_CLOSE_PAREN);
+ continue;
+ }
if (!strcmp("-e", arg)) {
if (1 < argc) {
- add_pattern(&opt, argv[1], "-e option", 0);
+ add_pattern(&opt, argv[1], "-e option", 0,
+ GREP_PATTERN);
argv++;
argc--;
continue;
@@ -824,7 +1099,8 @@ int cmd_grep(int argc, const char **argv
/* First unrecognized non-option token */
if (!opt.pattern_list) {
- add_pattern(&opt, arg, "command line", 0);
+ add_pattern(&opt, arg, "command line", 0,
+ GREP_PATTERN);
break;
}
else {
--
1.4.1.rc2.gfff62
^ permalink raw reply related
* Re: Incorporating gitweb-xmms2 features in trunk gitweb
From: Jakub Narebski @ 2006-06-30 9:59 UTC (permalink / raw)
To: Sham Chukoury, git
In-Reply-To: <449EF8A9.3080301@xmms.org>
Sham Chukoury <eleusis[@]xmms[.]org> wrote:
> Jakub Narebski wrote:
>> Now (from git 1.4.0) that gitweb is incorporated in main git.git
>> repository, and patches to it are accepted by Junio on git mailing
>> list, I have taken to adding new features to gitweb.
>>
>> I've planned on adding gitweb-xmms2 features (using separate topic
>> branches for each feature, like snapshots, hightlighting, committags).
>> Perhaps we could coordinate efforts?
>
> Coordination sounds great. What do you have in mind? :)
Actually it seems that I wouldn't have much time (at least in near future)
for work on gitweb. The main thing stopping me is that gitweb needs
refactoring before adding (or re-adding) new features, as it is written
partially at least in copy'n'paste style, AND waiting for Git.pm Perly git
interface (I'd like to have perl-only Git.pm and use it in gitweb, but
pasky who develops it uses XS for speed).
An example of such refactoring is your separation of navbar generation
code. Similar work was done by Sven Verdoolaege when introducing in-gitweb
snapshot code in
"gitweb and tar snapshots"
http://marc.theaimsgroup.com/?l=git&m=111909432415478&w=2
http://www.liacs.nl/~sverdool/gitweb.cgi?p=gitweb.git;a=summary
http://www.liacs.nl/~sverdool/gitweb.git#master
In my opinion your navbar code is too tied up with current navbar, while
sverdool is a little too perl-hackerish (e.g. there is only one instance,
i.e. root commit, where "top" part of navbar is not default, i.e. it
lacks "commitdiff" (to parent)).
>> For now from gitweb-xmms2.git I have only cherry-picked "Make CSS
>> readable" commit 561262030d58a6325f500b36d836dbe02a5abc68.
>
> Bear in mind that, since 'forking' (for lack of a better word) from v264, I
> haven't merged any changes from the 'official' gitweb tree.. Last time I
> checked, there's at least one changeset I reimplemented differently (perhaps
> wrongly). I need to go back and see what needs to be fixed properly..
gitweb-xmms2 merged quite cleanly with 1.4.0. It was later changes in next
(among others adding optional "blame" view for blobs, using old navbar
generation) that makes automatic merge fail.
> Going back to the point on coordination - I currently track bugs and feature
> requests for gitweb-xmms2 using the xmms2 bug tracker at
> http://bugs.xmms2.xmms.se (You'll need to select the 'Misc - gitweb' project
> from the dropdown at the top right of the page to see the relevant reports)
Check my two threads on gitweb wishlist features, and plans on refactoring
on git mailing list:
"[RFC] gitweb wishlist and TODO list"
Message-ID: <e79921$u0e$1@sea.gmane.org>
http://permalink.gmane.org/gmane.comp.version-control.git/22213
http://marc.theaimsgroup.com/?l=git&m=115082279425118&w=2
and
"gitweb refactoring"
Message-ID: <e7ed1r$9ve$1@sea.gmane.org>
http://permalink.gmane.org/gmane.comp.version-control.git/22345
http://marc.theaimsgroup.com/?l=git&m=115099031220954&w=2
P.S. Now that gitweb is included in git.git (from git version 1.4.0), you should
have easier to have your patches accepted into gitweb trunk.
--
Jakub Narebski
ShadeHawk on #git
^ permalink raw reply
* Re: [PATCH 4/4] save another call to git-update-index
From: Johannes Schindelin @ 2006-06-30 9:56 UTC (permalink / raw)
To: Alex Riesen; +Cc: Alex Riesen, git
In-Reply-To: <81b0412b0606300022k68d13dg8e292d9b768df51c@mail.gmail.com>
Hi,
On Fri, 30 Jun 2006, Alex Riesen wrote:
> On 6/30/06, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> >
> > FYI I've been just battling this pipe for a couple of hours. The first
> > steps were easy, but since I wanted to do it incrementally, the index has
> > to be written every so often, and I seem not to be able to get that right.
> >
> Are you sure? Does something use the index between starting update-index
> pipe and pclose?
Yes, I am sure you have to write the cache before git-read-tree and
git-write-tree ;-) I must have done something severely wrong, though,
since there are not too many places where they are called. The problem is
more likely that the cache has to be _read_, and _before_ the first
substituted call to git-update-index.
Ciao,
Dscho
^ permalink raw reply
* Re: GIt.xs merge status
From: Johannes Schindelin @ 2006-06-30 9:53 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Petr Baudis
In-Reply-To: <7vmzbvmny4.fsf_-_@assigned-by-dhcp.cox.net>
Hi,
On Thu, 29 Jun 2006, Junio C Hamano wrote:
> Junio C Hamano <junkio@cox.net> writes:
>
> > - Make sure Git.xs builds and installed result works fine on
> > all platforms we care about, including Cygwin and other
> > non-Linux boxes.
>
> Help wanted from the list here. One thing to note is that I
> understand Pasky is working on not using Devel::PPPort to make
> the code work with 5.6, so if your build dies with problems in
> that area you might want to wait until that is fixed.
I'll try it (it's in pu, right?). Note that breaking git-fmt-merge-msg
might be a good way to force somebody to rewrite it in C ;-)
Note that on my iBook (where I reported the Devel::PPPort problem), I _do_
have perl modules compiled from source, using SWIG. So, there _should_ be
no problem to get it to run (although I have problems with my eyes ever
since I looked into the code generated by SWIG).
Ciao,
Dscho
^ permalink raw reply
* Re: [PATCH] consider previous pack undeltified object state only when reusing delta data
From: Johannes Schindelin @ 2006-06-30 9:45 UTC (permalink / raw)
To: Nicolas Pitre; +Cc: Junio C Hamano, git
In-Reply-To: <Pine.LNX.4.64.0606292335190.1213@localhost.localdomain>
Hi,
On Thu, 29 Jun 2006, Nicolas Pitre wrote:
> Without this there would never be a chance to improve packing for
> previously undeltified objects.
Earlier this year, I was quite surprised to learn that multiple repackings
actually improved packing. Does that patch mean this feature is gone?
Ciao,
Dscho
^ permalink raw reply
* Re: [PATCH 2/4] make filepairs detachable
From: Alex Riesen @ 2006-06-30 8:21 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7v7j2zkrod.fsf@assigned-by-dhcp.cox.net>
On 6/30/06, Junio C Hamano <junkio@cox.net> wrote:
>
> > BTW, is there any chance we get the struct diff_filepair's
> > double-linked? They don't seem to be sorted. Will increase
> > the memory footprint, though.
>
> You do not necessarily have to do things in place. In fact, all
> of the standard diffcore transformers create a new queue, read
> from the old queue and place the filtered or munged result in
> the new queue, swap the global queued_diff variable to point at
> the new one and discard the old queue.
>
> See diff.c::diffcore_apply_filter() for the simplest example.
>
I see. Looks dangerous outside of diff.c though.
^ permalink raw reply
* Re: [PATCH] git-grep: --and to combine patterns with and instead of or
From: Junio C Hamano @ 2006-06-30 7:56 UTC (permalink / raw)
To: Matthias Lederhofer; +Cc: git
In-Reply-To: <E1FwDiI-0007Xp-2s@moooo.ath.cx>
Matthias Lederhofer <matled@gmx.net> writes:
> (Junio: please reply to this one, forgot the Cc in the first one :/)
Huh?
>> I personally feel FOO should not even exist. An option that
>> covers the entire expression to make operator precedence in it
>> sounds quite evil.
>>
>> I would say make --and bind tighter than --or and use parentheses as
>> needed.
> Ok, perhaps changing operator precedence is a bit much. What do you
> think of that then:
> ...
I see you are trying hard to think of a way to justify your
original prefix "--and" (or --FOO) implementation, but I simply
do not see much point in that. I doubt changing the default
operator from --or to --and is less confusing than changing the
precedence for the users, so you would hear the same "I
personally feel FOO should not even exist" objection from me.
^ permalink raw reply
* Re: [PATCH 2/4] make filepairs detachable
From: Junio C Hamano @ 2006-06-30 7:50 UTC (permalink / raw)
To: Alex Riesen; +Cc: git
In-Reply-To: <81b0412b0606300042r24931d9i5fad0e849b8de84c@mail.gmail.com>
"Alex Riesen" <raa.lkml@gmail.com> writes:
> BTW, is there any chance we get the struct diff_filepair's
> double-linked? They don't seem to be sorted. Will increase
> the memory footprint, though.
You do not necessarily have to do things in place. In fact, all
of the standard diffcore transformers create a new queue, read
from the old queue and place the filtered or munged result in
the new queue, swap the global queued_diff variable to point at
the new one and discard the old queue.
See diff.c::diffcore_apply_filter() for the simplest example.
^ permalink raw reply
* Re: [PATCH] git-grep: --and to combine patterns with and instead of or
From: Matthias Lederhofer @ 2006-06-30 7:46 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7v7j2zmgbu.fsf@assigned-by-dhcp.cox.net>
(Junio: please reply to this one, forgot the Cc in the first one :/)
Junio C Hamano wrote:
> Matthias Lederhofer <matled@gmx.net> writes:
>
> > OR and AND have precedence, so there are two possibilities, I'd take
> > the first one.
> > 1. OR, AND:
> > This will make it easier to read because OR can be skipped:
> > pat1 pat2 AND pat3 pat4
> > = pat1 OR pat2 AND pat3 OR pat4
> > = (pat1 OR pat2) AND (pat3 OR pat4)
> > 2. AND, OR:
> > This is a bit more logic if you think of AND as * and OR as +.
>
> > ... FOO should not be named --and imo but I don't have any idea
> > for a good name atm.
>
> I personally feel FOO should not even exist. An option that
> covers the entire expression to make operator precedence in it
> sounds quite evil.
>
> I would say make --and bind tighter than --or and use parentheses as
> needed.
Ok, perhaps changing operator precedence is a bit much. What do you
think of that then:
Operator precedence AND, OR. The FOO options changes the default
operator to AND. This also seems quite natural if you think of
AND as * and OR as +:
A B + C D = A * B + C * D = (A * B) + (C * D)
A few examples to get an impression how the command line could look
like:
A OR B OR (C AND D) => A B C AND D
(A OR B OR C) AND D => (A B C) AND D
A AND B AND (C OR D) => -FOO A B (C OR D)
(A AND B AND C) OR D => -FOO A B C OR D
Perhaps we even could use options which are similar to * and +, for
example:
- -* and -+ (-* should not be expanded often but is annoying anyway)
- -. and -+
- -t and -p (A -t B is A times B, A -p B is A plus B)
> Making --or optional sounds fine as that
> would make the default "multiple -e" case similar to what GNU
> grep does without any --and nor --or.
That's exactly what I was thinking about: make extended expressions
compatible to current grep options. This will confuse less people and
there is no need for an extra option to activate this.
^ 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