Commit 106c12f11873d270eb2c8b25bd82eaade0092e31

Russell Belfer 2013-09-23T13:31:15

Remove regex usage from places that don't need it In revwalk, we are doing a very simple check to see if a string contains wildcard characters, so a full regular expression match is not needed. In remote listing, now that we have git_config_foreach_match with full regular expression matching, we can take advantage of that and eliminate the regex here, replacing it with much simpler string manipulation.

diff --git a/src/remote.c b/src/remote.c
index 1540f10..95b907f 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -18,8 +18,6 @@
 #include "refspec.h"
 #include "fetchhead.h"
 
-#include <regex.h>
-
 static int add_refspec(git_remote *remote, const char *string, bool is_fetch)
 {
 	git_refspec *spec;
@@ -1075,35 +1073,28 @@ void git_remote_free(git_remote *remote)
 	git__free(remote);
 }
 
-struct cb_data {
-	git_vector *list;
-	regex_t *preg;
-};
-
-static int remote_list_cb(const git_config_entry *entry, void *data_)
+static int remote_list_cb(const git_config_entry *entry, void *payload)
 {
-	struct cb_data *data = (struct cb_data *)data_;
-	size_t nmatch = 2;
-	regmatch_t pmatch[2];
-	const char *name = entry->name;
+	git_vector *list = payload;
+	const char *name = entry->name + strlen("remote.");
+	size_t namelen = strlen(name);
+	char *remote_name;
 
-	if (!regexec(data->preg, name, nmatch, pmatch, 0)) {
-		char *remote_name = git__strndup(&name[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so);
-		GITERR_CHECK_ALLOC(remote_name);
+	/* we know name matches "remote.<stuff>.(push)?url" */
 
-		if (git_vector_insert(data->list, remote_name) < 0)
-			return -1;
-	}
+	if (!strcmp(&name[namelen - 4], ".url"))
+		remote_name = git__strndup(name, namelen - 4); /* strip ".url" */
+	else
+		remote_name = git__strndup(name, namelen - 8); /* strip ".pushurl" */
+	GITERR_CHECK_ALLOC(remote_name);
 
-	return 0;
+	return git_vector_insert(list, remote_name);
 }
 
 int git_remote_list(git_strarray *remotes_list, git_repository *repo)
 {
 	git_config *cfg;
 	git_vector list;
-	regex_t preg;
-	struct cb_data data;
 	int error;
 
 	if (git_repository_config__weakptr(&cfg, repo) < 0)
@@ -1112,18 +1103,13 @@ int git_remote_list(git_strarray *remotes_list, git_repository *repo)
 	if (git_vector_init(&list, 4, git__strcmp_cb) < 0)
 		return -1;
 
-	if (regcomp(&preg, "^remote\\.(.*)\\.(push)?url$", REG_EXTENDED) < 0) {
-		giterr_set(GITERR_OS, "Remote catch regex failed to compile");
-		return -1;
-	}
+	error = git_config_foreach_match(
+		cfg, "^remote\\..*\\.(push)?url$", remote_list_cb, &list);
 
-	data.list = &list;
-	data.preg = &preg;
-	error = git_config_foreach(cfg, remote_list_cb, &data);
-	regfree(&preg);
 	if (error < 0) {
 		size_t i;
 		char *elem;
+
 		git_vector_foreach(&list, i, elem) {
 			git__free(elem);
 		}
diff --git a/src/revwalk.c b/src/revwalk.c
index 9e1e39c..3dd14b4 100644
--- a/src/revwalk.c
+++ b/src/revwalk.c
@@ -14,8 +14,6 @@
 #include "git2/revparse.h"
 #include "merge.h"
 
-#include <regex.h>
-
 git_commit_list_node *git_revwalk__commit_lookup(
 	git_revwalk *walk, const git_oid *oid)
 {
@@ -181,48 +179,35 @@ static int push_glob_cb(const char *refname, void *data_)
 
 static int push_glob(git_revwalk *walk, const char *glob, int hide)
 {
+	int error = 0;
 	git_buf buf = GIT_BUF_INIT;
 	struct push_cb_data data;
-	regex_t preg;
+	size_t wildcard;
 
 	assert(walk && glob);
 
 	/* refs/ is implied if not given in the glob */
-	if (strncmp(glob, GIT_REFS_DIR, strlen(GIT_REFS_DIR))) {
-		git_buf_printf(&buf, GIT_REFS_DIR "%s", glob);
-	} else {
+	if (git__prefixcmp(glob, GIT_REFS_DIR) != 0)
+		git_buf_joinpath(&buf, GIT_REFS_DIR, glob);
+	else
 		git_buf_puts(&buf, glob);
-	}
 
 	/* If no '?', '*' or '[' exist, we append '/ *' to the glob */
-	memset(&preg, 0x0, sizeof(regex_t));
-	if (regcomp(&preg, "[?*[]", REG_EXTENDED)) {
-		giterr_set(GITERR_OS, "Regex failed to compile");
-		git_buf_free(&buf);
-		return -1;
-	}
-
-	if (regexec(&preg, glob, 0, NULL, 0))
-		git_buf_puts(&buf, "/*");
-
-	if (git_buf_oom(&buf))
-		goto on_error;
+	wildcard = strcspn(glob, "?*[");
+	if (!glob[wildcard])
+		git_buf_put(&buf, "/*", 2);
 
 	data.walk = walk;
 	data.hide = hide;
 
-	if (git_reference_foreach_glob(
-		walk->repo, git_buf_cstr(&buf), push_glob_cb, &data) < 0)
-		goto on_error;
-
-	regfree(&preg);
-	git_buf_free(&buf);
-	return 0;
+	if (git_buf_oom(&buf))
+		error = -1;
+	else
+		error = git_reference_foreach_glob(
+			walk->repo, git_buf_cstr(&buf), push_glob_cb, &data);
 
-on_error:
-	regfree(&preg);
 	git_buf_free(&buf);
-	return -1;
+	return error;
 }
 
 int git_revwalk_push_glob(git_revwalk *walk, const char *glob)