Skip to content

Commit 63307cb

Browse files
authored
Merge pull request libgit2#5226 from pks-t/pks/regexp-api
regexp: implement a new regular expression API
2 parents 7032537 + f585b12 commit 63307cb

File tree

14 files changed

+599
-300
lines changed

14 files changed

+599
-300
lines changed

cmake/Modules/FindPCRE2.cmake

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,14 @@ FIND_PATH(PCRE2_INCLUDE_DIR NAMES pcre2posix.h)
2020

2121
# Look for the library.
2222
FIND_LIBRARY(PCRE2_LIBRARY NAMES pcre2-8)
23-
FIND_LIBRARY(PCRE2_POSIX_LIBRARY NAMES pcre2-posix)
2423

2524
# Handle the QUIETLY and REQUIRED arguments and set PCRE2_FOUND to TRUE if all listed variables are TRUE.
2625
INCLUDE(FindPackageHandleStandardArgs)
27-
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE2 DEFAULT_MSG PCRE2_LIBRARY PCRE2_POSIX_LIBRARY PCRE2_INCLUDE_DIR)
26+
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE2 DEFAULT_MSG PCRE2_LIBRARY PCRE2_INCLUDE_DIR)
2827

2928
# Copy the results to the output variables.
3029
IF(PCRE2_FOUND)
31-
SET(PCRE2_LIBRARIES ${PCRE2_LIBRARY} ${PCRE2_POSIX_LIBRARY})
30+
SET(PCRE2_LIBRARIES ${PCRE2_LIBRARY})
3231
SET(PCRE2_INCLUDE_DIRS ${PCRE2_INCLUDE_DIR})
3332
ELSE(PCRE2_FOUND)
3433
SET(PCRE2_LIBRARIES)

src/common.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@
8888
#include "git2/deprecated.h"
8989

9090
#include "posix.h"
91-
#include "posix_regex.h"
9291

9392
#define DEFAULT_BUFSIZE 65536
9493
#define FILEIO_BUFSIZE DEFAULT_BUFSIZE

src/config.c

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@
77

88
#include "config.h"
99

10-
#include "sysdir.h"
1110
#include "git2/config.h"
1211
#include "git2/sys/config.h"
13-
#include "vector.h"
12+
1413
#include "buf_text.h"
1514
#include "config_backend.h"
15+
#include "regexp.h"
16+
#include "sysdir.h"
1617
#include "transaction.h"
18+
#include "vector.h"
1719
#if GIT_WIN32
1820
# include <windows.h>
1921
#endif
@@ -345,7 +347,7 @@ typedef struct {
345347
git_config_iterator parent;
346348
git_config_iterator *current;
347349
const git_config *cfg;
348-
p_regex_t regex;
350+
git_regexp regex;
349351
size_t i;
350352
} all_iter;
351353

@@ -423,7 +425,7 @@ static int all_iter_glob_next(git_config_entry **entry, git_config_iterator *_it
423425
*/
424426
while ((error = all_iter_next(entry, _iter)) == 0) {
425427
/* skip non-matching keys if regexp was provided */
426-
if (p_regexec(&iter->regex, (*entry)->name, 0, NULL, 0) != 0)
428+
if (git_regexp_match(&iter->regex, (*entry)->name) != 0)
427429
continue;
428430

429431
/* and simply return if we like the entry's name */
@@ -447,7 +449,7 @@ static void all_iter_glob_free(git_config_iterator *_iter)
447449
{
448450
all_iter *iter = (all_iter *) _iter;
449451

450-
p_regfree(&iter->regex);
452+
git_regexp_dispose(&iter->regex);
451453
all_iter_free(_iter);
452454
}
453455

@@ -480,8 +482,7 @@ int git_config_iterator_glob_new(git_config_iterator **out, const git_config *cf
480482
iter = git__calloc(1, sizeof(all_iter));
481483
GIT_ERROR_CHECK_ALLOC(iter);
482484

483-
if ((result = p_regcomp(&iter->regex, regexp, P_REG_EXTENDED)) != 0) {
484-
git_error_set_regex(&iter->regex, result);
485+
if ((result = git_regexp_compile(&iter->regex, regexp, 0)) < 0) {
485486
git__free(iter);
486487
return -1;
487488
}
@@ -510,18 +511,13 @@ int git_config_backend_foreach_match(
510511
{
511512
git_config_entry *entry;
512513
git_config_iterator* iter;
513-
p_regex_t regex;
514+
git_regexp regex;
514515
int error = 0;
515516

516517
assert(backend && cb);
517518

518-
if (regexp != NULL) {
519-
if ((error = p_regcomp(&regex, regexp, P_REG_EXTENDED)) != 0) {
520-
git_error_set_regex(&regex, error);
521-
p_regfree(&regex);
522-
return -1;
523-
}
524-
}
519+
if (regexp && git_regexp_compile(&regex, regexp, 0) < 0)
520+
return -1;
525521

526522
if ((error = backend->iterator(&iter, backend)) < 0) {
527523
iter = NULL;
@@ -530,7 +526,7 @@ int git_config_backend_foreach_match(
530526

531527
while (!(iter->next(&entry, iter) < 0)) {
532528
/* skip non-matching keys if regexp was provided */
533-
if (regexp && p_regexec(&regex, entry->name, 0, NULL, 0) != 0)
529+
if (regexp && git_regexp_match(&regex, entry->name) != 0)
534530
continue;
535531

536532
/* abort iterator on non-zero return value */
@@ -541,7 +537,7 @@ int git_config_backend_foreach_match(
541537
}
542538

543539
if (regexp != NULL)
544-
p_regfree(&regex);
540+
git_regexp_dispose(&regex);
545541

546542
iter->free(iter);
547543

@@ -981,7 +977,7 @@ typedef struct {
981977
git_config_iterator parent;
982978
git_config_iterator *iter;
983979
char *name;
984-
p_regex_t regex;
980+
git_regexp regex;
985981
int have_regex;
986982
} multivar_iter;
987983

@@ -997,7 +993,7 @@ static int multivar_iter_next(git_config_entry **entry, git_config_iterator *_it
997993
if (!iter->have_regex)
998994
return 0;
999995

1000-
if (p_regexec(&iter->regex, (*entry)->value, 0, NULL, 0) == 0)
996+
if (git_regexp_match(&iter->regex, (*entry)->value) == 0)
1001997
return 0;
1002998
}
1003999

@@ -1012,7 +1008,7 @@ void multivar_iter_free(git_config_iterator *_iter)
10121008

10131009
git__free(iter->name);
10141010
if (iter->have_regex)
1015-
p_regfree(&iter->regex);
1011+
git_regexp_dispose(&iter->regex);
10161012
git__free(iter);
10171013
}
10181014

@@ -1032,13 +1028,8 @@ int git_config_multivar_iterator_new(git_config_iterator **out, const git_config
10321028
goto on_error;
10331029

10341030
if (regexp != NULL) {
1035-
error = p_regcomp(&iter->regex, regexp, P_REG_EXTENDED);
1036-
if (error != 0) {
1037-
git_error_set_regex(&iter->regex, error);
1038-
error = -1;
1039-
p_regfree(&iter->regex);
1031+
if ((error = git_regexp_compile(&iter->regex, regexp, 0)) < 0)
10401032
goto on_error;
1041-
}
10421033

10431034
iter->have_regex = 1;
10441035
}

src/config_file.c

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "config_entries.h"
1919
#include "config_parse.h"
2020
#include "filebuf.h"
21+
#include "regexp.h"
2122
#include "strmap.h"
2223
#include "sysdir.h"
2324
#include "wildmatch.h"
@@ -61,7 +62,7 @@ typedef struct {
6162

6263
static int config_read(git_config_entries *entries, const git_repository *repo, config_file *file, git_config_level_t level, int depth);
6364
static int config_read_buffer(git_config_entries *entries, const git_repository *repo, config_file *file, git_config_level_t level, int depth, const char *buf, size_t buflen);
64-
static int config_write(config_file_backend *cfg, const char *orig_key, const char *key, const p_regex_t *preg, const char *value);
65+
static int config_write(config_file_backend *cfg, const char *orig_key, const char *key, const git_regexp *preg, const char *value);
6566
static char *escape_value(const char *ptr);
6667

6768
/**
@@ -350,29 +351,25 @@ static int config_set_multivar(
350351
git_config_backend *cfg, const char *name, const char *regexp, const char *value)
351352
{
352353
config_file_backend *b = GIT_CONTAINER_OF(cfg, config_file_backend, parent);
353-
char *key;
354-
p_regex_t preg;
354+
git_regexp preg;
355355
int result;
356+
char *key;
356357

357358
assert(regexp);
358359

359360
if ((result = git_config__normalize_name(name, &key)) < 0)
360361
return result;
361362

362-
result = p_regcomp(&preg, regexp, P_REG_EXTENDED);
363-
if (result != 0) {
364-
git_error_set_regex(&preg, result);
365-
result = -1;
363+
if ((result = git_regexp_compile(&preg, regexp, 0)) < 0)
366364
goto out;
367-
}
368365

369366
/* If we do have it, set call config_write() and reload */
370367
if ((result = config_write(b, name, key, &preg, value)) < 0)
371368
goto out;
372369

373370
out:
374371
git__free(key);
375-
p_regfree(&preg);
372+
git_regexp_dispose(&preg);
376373

377374
return result;
378375
}
@@ -412,7 +409,7 @@ static int config_delete_multivar(git_config_backend *cfg, const char *name, con
412409
config_file_backend *b = GIT_CONTAINER_OF(cfg, config_file_backend, parent);
413410
git_config_entries *entries = NULL;
414411
git_config_entry *entry = NULL;
415-
p_regex_t preg = { 0 };
412+
git_regexp preg = GIT_REGEX_INIT;
416413
char *key = NULL;
417414
int result;
418415

@@ -430,19 +427,16 @@ static int config_delete_multivar(git_config_backend *cfg, const char *name, con
430427
goto out;
431428
}
432429

433-
if ((result = p_regcomp(&preg, regexp, P_REG_EXTENDED)) != 0) {
434-
git_error_set_regex(&preg, result);
435-
result = -1;
430+
if ((result = git_regexp_compile(&preg, regexp, 0)) < 0)
436431
goto out;
437-
}
438432

439433
if ((result = config_write(b, name, key, &preg, NULL)) < 0)
440434
goto out;
441435

442436
out:
443437
git_config_entries_free(entries);
444438
git__free(key);
445-
p_regfree(&preg);
439+
git_regexp_dispose(&preg);
446440
return result;
447441
}
448442

@@ -928,7 +922,7 @@ struct write_data {
928922
const char *section;
929923
const char *orig_name;
930924
const char *name;
931-
const p_regex_t *preg;
925+
const git_regexp *preg;
932926
const char *value;
933927
};
934928

@@ -1033,7 +1027,7 @@ static int write_on_variable(
10331027

10341028
/* If we have a regex to match the value, see if it matches */
10351029
if (has_matched && write_data->preg != NULL)
1036-
has_matched = (p_regexec(write_data->preg, var_value, 0, NULL, 0) == 0);
1030+
has_matched = (git_regexp_match(write_data->preg, var_value) == 0);
10371031

10381032
/* If this isn't the name/value we're looking for, simply dump the
10391033
* existing data back out and continue on.
@@ -1094,7 +1088,8 @@ static int write_on_eof(
10941088
/*
10951089
* This is pretty much the parsing, except we write out anything we don't have
10961090
*/
1097-
static int config_write(config_file_backend *cfg, const char *orig_key, const char *key, const p_regex_t *preg, const char* value)
1091+
static int config_write(config_file_backend *cfg, const char *orig_key, const char *key, const git_regexp *preg, const char* value)
1092+
10981093
{
10991094
char *orig_section = NULL, *section = NULL, *orig_name, *name, *ldot;
11001095
git_buf buf = GIT_BUF_INIT, contents = GIT_BUF_INIT;

src/diff_driver.c

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "map.h"
1616
#include "buf_text.h"
1717
#include "config.h"
18+
#include "regexp.h"
1819
#include "repository.h"
1920

2021
typedef enum {
@@ -25,7 +26,7 @@ typedef enum {
2526
} git_diff_driver_t;
2627

2728
typedef struct {
28-
p_regex_t re;
29+
git_regexp re;
2930
int flags;
3031
} git_diff_driver_pattern;
3132

@@ -39,7 +40,7 @@ struct git_diff_driver {
3940
uint32_t binary_flags;
4041
uint32_t other_flags;
4142
git_array_t(git_diff_driver_pattern) fn_patterns;
42-
p_regex_t word_pattern;
43+
git_regexp word_pattern;
4344
char name[GIT_FLEX_ARRAY];
4445
};
4546

@@ -113,7 +114,7 @@ static int diff_driver_add_patterns(
113114
if (error < 0)
114115
break;
115116

116-
if ((error = p_regcomp(&pat->re, buf.ptr, regex_flags)) != 0) {
117+
if ((error = git_regexp_compile(&pat->re, buf.ptr, regex_flags)) != 0) {
117118
/*
118119
* TODO: issue a warning
119120
*/
@@ -130,7 +131,7 @@ static int diff_driver_add_patterns(
130131

131132
static int diff_driver_xfuncname(const git_config_entry *entry, void *payload)
132133
{
133-
return diff_driver_add_patterns(payload, entry->value, P_REG_EXTENDED);
134+
return diff_driver_add_patterns(payload, entry->value, 0);
134135
}
135136

136137
static int diff_driver_funcname(const git_config_entry *entry, void *payload)
@@ -205,16 +206,12 @@ static int git_diff_driver_builtin(
205206

206207
if (ddef->fns &&
207208
(error = diff_driver_add_patterns(
208-
drv, ddef->fns, ddef->flags | P_REG_EXTENDED)) < 0)
209+
drv, ddef->fns, ddef->flags)) < 0)
209210
goto done;
210211

211212
if (ddef->words &&
212-
(error = p_regcomp(
213-
&drv->word_pattern, ddef->words, ddef->flags | P_REG_EXTENDED)))
214-
{
215-
error = git_error_set_regex(&drv->word_pattern, error);
213+
(error = git_regexp_compile(&drv->word_pattern, ddef->words, ddef->flags)) < 0)
216214
goto done;
217-
}
218215

219216
if ((error = git_strmap_set(reg->drivers, drv->name, drv)) < 0)
220217
goto done;
@@ -316,11 +313,10 @@ static int git_diff_driver_load(
316313
goto done;
317314
if (!ce || !ce->value)
318315
/* no diff.<driver>.wordregex, so just continue */;
319-
else if (!(error = p_regcomp(&drv->word_pattern, ce->value, P_REG_EXTENDED)))
316+
else if (!(error = git_regexp_compile(&drv->word_pattern, ce->value, 0)))
320317
found_driver = true;
321318
else {
322319
/* TODO: warn about bad regex instead of failure */
323-
error = git_error_set_regex(&drv->word_pattern, error);
324320
goto done;
325321
}
326322

@@ -400,10 +396,10 @@ void git_diff_driver_free(git_diff_driver *driver)
400396
return;
401397

402398
for (i = 0; i < git_array_size(driver->fn_patterns); ++i)
403-
p_regfree(& git_array_get(driver->fn_patterns, i)->re);
399+
git_regexp_dispose(& git_array_get(driver->fn_patterns, i)->re);
404400
git_array_clear(driver->fn_patterns);
405401

406-
p_regfree(&driver->word_pattern);
402+
git_regexp_dispose(&driver->word_pattern);
407403

408404
git__free(driver);
409405
}
@@ -451,19 +447,19 @@ static int diff_context_line__pattern_match(
451447
git_diff_driver *driver, git_buf *line)
452448
{
453449
size_t i, maxi = git_array_size(driver->fn_patterns);
454-
p_regmatch_t pmatch[2];
450+
git_regmatch pmatch[2];
455451

456452
for (i = 0; i < maxi; ++i) {
457453
git_diff_driver_pattern *pat = git_array_get(driver->fn_patterns, i);
458454

459-
if (!p_regexec(&pat->re, line->ptr, 2, pmatch, 0)) {
455+
if (!git_regexp_search(&pat->re, line->ptr, 2, pmatch)) {
460456
if (pat->flags & REG_NEGATE)
461457
return false;
462458

463459
/* use pmatch data to trim line data */
464-
i = (pmatch[1].rm_so >= 0) ? 1 : 0;
465-
git_buf_consume(line, git_buf_cstr(line) + pmatch[i].rm_so);
466-
git_buf_truncate(line, pmatch[i].rm_eo - pmatch[i].rm_so);
460+
i = (pmatch[1].start >= 0) ? 1 : 0;
461+
git_buf_consume(line, git_buf_cstr(line) + pmatch[i].start);
462+
git_buf_truncate(line, pmatch[i].end - pmatch[i].start);
467463
git_buf_rtrim(line);
468464

469465
return true;

0 commit comments

Comments
 (0)