3

For example if I need replace some string to %teamcity.agent.work.dir%\\nd_r\\bin\\isf. But if variable teamcity.agent.work.dir is C:\BuildAgent\work\, it removes all backslashes and replace text to C:BuildAgentwork\nd_r\bin\isf.

How I can escape all backslashes in variable, if I initially don't know about it's value?

\Q%env.NDRIVE%\E\nd_r\bin\isf - it doesn't work.

Mois
  • 107
  • 8

3 Answers3

3

TeamCity does not support additional processing of values in %-references, it can only be used "as is".

In your case, possible workarounds are:

  • do not use File content replacer and perform the related logic as a first step in the build in a script where you can handle the escaping, if necessary;
  • escape the value and supply to TeamCity as a parameter in already escaped form. Since File content replacer works before the build steps, this can be done in a previous build in the build chain and the parameter can be used from the build in the chain;
  • write a TeamCity plugin which will provide escaped value for a predefined set of parameters
Yaegor
  • 1,771
  • 9
  • 12
1

Since TeamCity 2017.1, File Content Replacer can run in the fixed strings mode (similar to that of grep -F), as opposed to the original regex mode:

File Content Replacer in FIXED_STRINGS mode

If you use versioned settings (either XML or Kotlin DSL variant), there's yet another mode available to you (in addition to REGEX and FIXED_STRINGS): REGEX_MIXED. In this mode, the search pattern will still be interpreted as a regular expression, but the replacement text will be quoted so that \ and $ characters will no longer have any special meaning.

If you export your settings to Kotlin, sample File Content Replacer configuration might look like:

features {
    replaceContent {
        fileRules = "**/*"
        pattern = "(?iu)the\h+pattern\h+to\h+search\h+for"
        regexMode = FileContentReplacer.RegexMode.REGEX_MIXED
        replacement = """%teamcity.agent.work.dir%\nd_r\bin\isf"""
    }
}
Bass
  • 4,977
  • 2
  • 36
  • 82
0

There is another solution, but it's a bit of a hack. Simply do the replacement in two stages with two separate file-content replacers.

  • The first one should be a regex matcher. It finds the string you want replaced using a regex pattern, and replaces it with a fixed, known string (a GUID will do, or any unique magic string)
  • The second file-content replacer matches the same files, but is a fixed-string matcher, and replaces the fixed string from the first step with the parameter value. Because it's a fixed-string matcher, backslashes in the parameter value are preserved.

The only small problem with this approach is that teamcity doesn't allow reordering of build features, which suggests the order of execution might not be guaranteed. But so far it's worked for me.

ben
  • 1,441
  • 2
  • 16
  • 21