Merge pull request #1864 from libgit2/minimize-regex-usage Minimize regex usage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
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)