Skip to content

Commit 29c7642

Browse files
committed
Added use_non_convergent to pattern_matching promise in edit_line
Ticket: ENT-3417 Signed-off-by: Victor Moene <[email protected]>
1 parent 4bff865 commit 29c7642

File tree

2 files changed

+25
-10
lines changed

2 files changed

+25
-10
lines changed

cf-agent/files_editline.c

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,6 +1263,7 @@ static bool ReplacePatterns(EvalContext *ctx, Item *file_start, Item *file_end,
12631263
assert(a != NULL);
12641264
assert(pp != NULL);
12651265
assert(edcontext != NULL);
1266+
bool use_non_convergent = PromiseGetConstraintAsBoolean(ctx, "use_non_convergent", pp);
12661267

12671268
char line_buff[CF_EXPANDSIZE];
12681269
char after[CF_BUFSIZE];
@@ -1330,17 +1331,24 @@ static bool ReplacePatterns(EvalContext *ctx, Item *file_start, Item *file_end,
13301331
break;
13311332
}
13321333
}
1333-
1334+
char line_buff_cp[CF_EXPANDSIZE];
13341335
if (NotAnchored(pp->promiser) && BlockTextMatch(ctx, pp->promiser, line_buff, &start_off, &end_off))
13351336
{
1336-
RecordInterruption(ctx, pp, a,
1337-
"Promised replacement '%s' on line '%s' for pattern '%s'"
1338-
" is not convergent while editing '%s'"
1339-
" (regular expression matches the replacement string)",
1340-
line_buff, ip->name, pp->promiser, edcontext->filename);
1341-
*result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED);
1342-
PromiseRef(LOG_LEVEL_ERR, pp);
1343-
break;
1337+
strlcpy(line_buff_cp, line_buff, sizeof(line_buff_cp));
1338+
strlcpy(after, line_buff_cp + end_off, sizeof(after));
1339+
snprintf(line_buff_cp + start_off, sizeof(line_buff_cp) - start_off,
1340+
"%s%s", BufferData(replace), after);
1341+
1342+
if (!use_non_convergent || (strlen(line_buff) != strlen(line_buff_cp))) {
1343+
RecordInterruption(ctx, pp, a,
1344+
"Promised replacement '%s' on line '%s' for pattern '%s'"
1345+
" is not convergent while editing '%s'"
1346+
" (regular expression matches the replacement string)",
1347+
line_buff, ip->name, pp->promiser, edcontext->filename);
1348+
*result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED);
1349+
PromiseRef(LOG_LEVEL_ERR, pp);
1350+
break;
1351+
}
13441352
}
13451353

13461354
if (!MakingChanges(ctx, pp, a, result, "replace pattern '%s' in '%s'", pp->promiser,
@@ -1366,8 +1374,14 @@ static bool ReplacePatterns(EvalContext *ctx, Item *file_start, Item *file_end,
13661374
break;
13671375
}
13681376

1369-
if (BlockTextMatch(ctx, pp->promiser, ip->name, &start_off, &end_off))
1377+
if (BlockTextMatch(ctx, pp->promiser, ip->name, &start_off, &end_off) && (!use_non_convergent
1378+
|| (strlen(line_buff) != strlen(line_buff_cp))))
13701379
{
1380+
strlcpy(line_buff_cp, line_buff, sizeof(line_buff_cp));
1381+
strlcpy(after, line_buff_cp + end_off, sizeof(after));
1382+
snprintf(line_buff_cp + start_off, sizeof(line_buff_cp) - start_off,
1383+
"%s%s", BufferData(replace), after);
1384+
13711385
RecordInterruption(ctx, pp, a,
13721386
"Promised replacement '%s' for pattern '%s' is not properly convergent while editing '%s'"
13731387
" (pattern still matches the end-state replacement string '%s', consider use"

libpromises/mod_files.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ static const ConstraintSyntax CF_COLUMN_BODIES[] =
131131
static const ConstraintSyntax CF_REPLACE_BODIES[] =
132132
{
133133
ConstraintSyntaxNewBody("replace_with", &replace_with_body, "Search-replace pattern", SYNTAX_STATUS_NORMAL),
134+
ConstraintSyntaxNewBool("use_non_convergent", "Allow to use non-convergent regular expressions in replace_patterns. Defaults to false", SYNTAX_STATUS_NORMAL),
134135
ConstraintSyntaxNewNull()
135136
};
136137

0 commit comments

Comments
 (0)