use of com.google.copybara.doc.annotations.Example in project copybara by google.
the class Core method todoReplace.
@SuppressWarnings("unused")
@StarlarkMethod(name = "todo_replace", doc = "Replace Google style TODOs. For example `TODO(username, othername)`.", parameters = { @Param(name = "tags", named = true, allowedTypes = { @ParamType(type = net.starlark.java.eval.Sequence.class, generic1 = String.class) }, doc = "Prefix tag to look for", defaultValue = "['TODO', 'NOTE']"), @Param(name = "mapping", named = true, doc = "Mapping of users/strings", defaultValue = "{}"), @Param(name = "mode", named = true, doc = "Mode for the replace:<ul><li>'MAP_OR_FAIL': Try to use the mapping and if not" + " found fail.</li><li>'MAP_OR_IGNORE': Try to use the mapping but ignore if" + " no mapping found.</li><li>'MAP_OR_DEFAULT': Try to use the mapping and use" + " the default if not found.</li><li>'SCRUB_NAMES': Scrub all names from" + " TODOs. Transforms 'TODO(foo)' to 'TODO'</li><li>'USE_DEFAULT': Replace any" + " TODO(foo, bar) with TODO(default_string)</li></ul>", defaultValue = "'MAP_OR_IGNORE'"), @Param(name = "paths", named = true, allowedTypes = { @ParamType(type = Glob.class), @ParamType(type = NoneType.class) }, doc = "A glob expression relative to the workdir representing the files to apply the" + " transformation. For example, glob([\"**.java\"]), matches all java files" + " recursively. Defaults to match all the files recursively.", defaultValue = "None"), @Param(name = "default", named = true, allowedTypes = { @ParamType(type = String.class), @ParamType(type = NoneType.class) }, doc = "Default value if mapping not found. Only valid for 'MAP_OR_DEFAULT' or" + " 'USE_DEFAULT' modes", defaultValue = "None"), @Param(name = "ignore", named = true, allowedTypes = { @ParamType(type = String.class), @ParamType(type = NoneType.class) }, doc = "If set, elements within TODO (with usernames) that match the regex will be " + "ignored. For example ignore = \"foo\" would ignore \"foo\" in " + "\"TODO(foo,bar)\" but not \"bar\".", defaultValue = "None") }, useStarlarkThread = true)
@DocDefault(field = "paths", value = "glob([\"**\"])")
@Example(title = "Simple update", before = "Replace TODOs and NOTES for users in the mapping:", code = "core.todo_replace(\n" + " mapping = {\n" + " 'test1' : 'external1',\n" + " 'test2' : 'external2'\n" + " }\n" + ")", after = "Would replace texts like TODO(test1) or NOTE(test1, test2) with TODO(external1)" + " or NOTE(external1, external2)")
@Example(title = "Scrubbing", before = "Remove text from inside TODOs", code = "core.todo_replace(\n" + " mode = 'SCRUB_NAMES'\n" + ")", after = "Would replace texts like TODO(test1): foo or NOTE(test1, test2):foo with TODO:foo" + " and NOTE:foo")
@Example(title = "Ignoring Regex Patterns", before = "Ignore regEx inside TODOs when scrubbing/mapping", code = "core.todo_replace(\n" + " mapping = { 'aaa' : 'foo'},\n" + " ignore = 'b/.*'\n)", after = "Would replace texts like TODO(b/123, aaa) with TODO(b/123, foo)")
public TodoReplace todoReplace(// <String>
net.starlark.java.eval.Sequence<?> skyTags, // <String, String>
Dict<?, ?> skyMapping, String modeStr, Object paths, Object skyDefault, Object regexToIgnore, StarlarkThread thread) throws EvalException {
Mode mode = stringToEnum("mode", modeStr, Mode.class);
Map<String, String> mapping = SkylarkUtil.convertStringMap(skyMapping, "mapping");
String defaultString = convertFromNoneable(skyDefault, /*defaultValue=*/
null);
ImmutableList<String> tags = ImmutableList.copyOf(SkylarkUtil.convertStringList(skyTags, "tags"));
String ignorePattern = convertFromNoneable(regexToIgnore, null);
Pattern regexIgnorelist = ignorePattern != null ? Pattern.compile(ignorePattern) : null;
check(!tags.isEmpty(), "'tags' cannot be empty");
if (mode == Mode.MAP_OR_DEFAULT || mode == Mode.USE_DEFAULT) {
check(defaultString != null, "'default' needs to be set for mode '%s'", mode);
} else {
check(defaultString == null, "'default' cannot be used for mode '%s'", mode);
}
if (mode == Mode.USE_DEFAULT || mode == Mode.SCRUB_NAMES) {
check(mapping.isEmpty(), "'mapping' cannot be used with mode %s", mode);
}
return new TodoReplace(thread.getCallerLocation(), convertFromNoneable(paths, Glob.ALL_FILES), tags, mode, mapping, defaultString, workflowOptions.parallelizer(), regexIgnorelist);
}
use of com.google.copybara.doc.annotations.Example in project copybara by google.
the class MarkdownRenderer method module.
private CharSequence module(DocModule module, int level) {
StringBuilder sb = new StringBuilder();
sb.append(title(level, module.name));
sb.append(module.description).append("\n\n");
if (!module.fields.isEmpty()) {
sb.append(title(level + 2, "Fields:"));
sb.append(tableHeader("Name", "Description"));
for (DocField field : module.fields) {
sb.append(tableRow(field.name, String.format("%s<br><p>%s</p>", typeName(field.type), field.description)));
}
sb.append("\n");
}
sb.append(flags(module.flags));
for (DocFunction func : module.functions) {
sb.append("<a id=\"").append(func.name).append("\" aria-hidden=\"true\"></a>");
sb.append(title(level + 1, func.name));
sb.append(func.description);
sb.append("\n\n");
if (func.returnType != null) {
sb.append(typeName(func.returnType)).append(" ");
}
sb.append("`").append(func.name).append("(");
Joiner.on(", ").appendTo(sb, Lists.transform(func.params, p -> p.name + (p.defaultValue == null ? "" : "=" + p.defaultValue)));
sb.append(")`\n\n");
if (!func.params.isEmpty()) {
sb.append(title(level + 2, "Parameters:"));
sb.append(tableHeader("Parameter", "Description"));
for (DocParam param : func.params) {
sb.append(tableRow(param.name, String.format("%s<br><p>%s</p>", param.allowedTypes.stream().map(this::typeName).collect(joining(" or ")), param.description)));
}
sb.append("\n");
}
if (!func.examples.isEmpty()) {
sb.append(title(level + 2, func.examples.size() == 1 ? "Example:" : "Examples:"));
for (DocExample example : func.examples) {
sb.append(example(level + 3, example.example));
}
sb.append("\n");
}
sb.append(flags(func.flags));
}
return sb;
}
use of com.google.copybara.doc.annotations.Example in project copybara by google.
the class MetadataModule method scrubber.
@SuppressWarnings("unused")
@StarlarkMethod(name = "scrubber", doc = "Removes part of the change message using a regex", parameters = { @Param(name = "regex", named = true, doc = "Any text matching the regex will be removed. Note that the regex is" + " runs in multiline mode."), @Param(name = "msg_if_no_match", allowedTypes = { @ParamType(type = String.class), @ParamType(type = NoneType.class) }, named = true, doc = "If set, Copybara will use this text when the scrubbing regex doesn't match.", defaultValue = "None"), @Param(name = "fail_if_no_match", named = true, doc = "If set, msg_if_no_match must be None and then fail if the scrubbing " + "regex doesn't match. ", defaultValue = "False"), @Param(name = "replacement", named = true, doc = "Text replacement for the matching substrings. References to regex group" + " numbers can be used in the form of $1, $2, etc.", defaultValue = "''") }, useStarlarkThread = true)
@Example(title = "Remove from a keyword to the end of the message", before = "When change messages are in the following format:\n\n" + "```\n" + "Public change description\n\n" + "This is a public description for a commit\n\n" + "CONFIDENTIAL:\n" + "This fixes internal project foo-bar\n" + "```\n\n" + "Using the following transformation:", code = "metadata.scrubber('(^|\\n)CONFIDENTIAL:(.|\\n)*')", after = "Will remove the confidential part, leaving the message as:\n\n" + "```\n" + "Public change description\n\n" + "This is a public description for a commit\n" + "```\n\n")
@Example(title = "Keep only message enclosed in tags", before = "The previous example is prone to leak confidential information since a developer could" + " easily forget to include the CONFIDENTIAL label. A different approach for this" + " is to scrub everything by default except what is explicitly allowed. For" + " example, the following scrubber would remove anything not enclosed in" + " <public></public> tags:\n", code = "metadata.scrubber('^(?:\\n|.)*<public>((?:\\n|.)*)</public>(?:\\n|.)*$', " + "replacement = '$1')", after = "So a message like:\n\n" + "```\n" + "this\nis\nvery confidential<public>but this is public\nvery public\n</public>" + "\nand this is a secret too\n" + "```\n\n" + "would be transformed into:\n\n" + "```\n" + "but this is public\nvery public\n" + "```\n\n")
@Example(title = "Use default msg when the scrubbing regex doesn't match", before = "Assign msg_if_no_match a default msg. For example:\n", code = "metadata.scrubber('^(?:\\n|.)*<public>((?:\\n|.)*)</public>(?:\\n|.)*$', " + "msg_if_no_match = 'Internal Change.', replacement = '$1')", after = "So a message like:\n\n" + "```\n" + "this\nis\nvery confidential\nThis is not public msg.\n" + "\nand this is a secret too\n" + "```\n\n" + "would be transformed into:\n\n" + "```\n" + "Internal Change.\n" + "```\n\n")
@Example(title = "Fail if the scrubbing regex doesn't match", before = "Set fail_if_no_match to true", code = "metadata.scrubber('^(?:\\n|.)*<public>((?:\\n|.)*)</public>(?:\\n|.)*$', " + "fail_if_no_match = True, replacement = '$1')", after = "So a message like:\n\n" + "```\n" + "this\n" + "is\n" + "very confidential\n" + "but this is not public\n" + "\n" + "and this is a secret too\n" + "\n" + "```\n\n" + "This would fail. Error msg:\n\n" + "```\n" + "Scrubber regex: \'^(?:\\n" + "|.)*<public>((?:\\n" + "|.)*)</public>(?:\\n" + "|.)*$\' didn't match for description: this\n" + "is\n" + "very confidential\n" + "but this is not public\n" + "\n" + "and this is a secret too\n" + "```\n\n")
public Transformation scrubber(String regex, Object msgIfNoMatchObj, Boolean failIfNoMatch, String replacement, StarlarkThread thread) throws EvalException {
Pattern pattern;
try {
pattern = Pattern.compile(regex, Pattern.MULTILINE);
} catch (PatternSyntaxException e) {
throw Starlark.errorf("Invalid regex expression: %s", e.getMessage());
}
String msgIfNoMatch = convertFromNoneable(msgIfNoMatchObj, null);
check(!failIfNoMatch || msgIfNoMatch == null, "If fail_if_no_match is true, msg_if_no_match should be None.");
return new Scrubber(pattern, msgIfNoMatch, failIfNoMatch, replacement, thread.getCallerLocation());
}
use of com.google.copybara.doc.annotations.Example in project copybara by google.
the class MetadataModule method mapReferences.
@SuppressWarnings("unused")
@StarlarkMethod(name = "map_references", doc = "Allows updating links to references in commit messages to match the destination's " + "format. Note that this will only consider the 5000 latest commits.", parameters = { @Param(name = "before", named = true, doc = "Template for origin references in the change message. Use a '${reference}'" + " token to capture the actual references. E.g. if the origin uses links" + " like 'http://changes?1234', the template would be " + "'http://changes?${reference}', with reference_regex = '[0-9]+'"), @Param(name = "after", named = true, doc = "Format for destination references in the change message. Use a '${reference}'" + " token to represent the destination reference. E.g. if the destination uses" + " links like 'http://changes?1234', the template would be " + "'http://changes?${reference}', with reference_regex = '[0-9]+'"), @Param(name = "regex_groups", defaultValue = "{}", named = true, doc = "Regexes for the ${reference} token's content. Requires one 'before_ref' entry" + " matching the ${reference} token's content on the before side. Optionally" + " accepts one 'after_ref' used for validation." + " Copybara uses [re2](https://github.com/google/re2/wiki/Syntax) syntax."), @Param(name = "additional_import_labels", named = true, allowedTypes = { @ParamType(type = Sequence.class, generic1 = String.class) }, defaultValue = "[]", doc = "Meant to be used when migrating from another tool: Per default, copybara will" + " only recognize the labels defined in the workflow's endpoints. The tool" + " will use these additional labels to find labels created by other" + " invocations and tools.") }, useStarlarkThread = true)
@Example(title = "Map references, origin source of truth", before = "Finds links to commits in change messages, searches destination to find the equivalent" + " reference in destination. Then replaces matches of 'before' with 'after'," + " replacing the subgroup matched with the destination reference. Assume a message" + " like 'Fixes bug introduced in origin/abcdef', where the origin change 'abcdef'" + " was migrated as '123456' to the destination.", code = "metadata.map_references(\n" + " before = \"origin/${reference}\",\n" + " after = \"destination/${reference}\",\n" + " regex_groups = {\n" + " \"before_ref\": \"[0-9a-f]+\",\n" + " \"after_ref\": \"[0-9]+\",\n" + " },\n" + ")", after = "This would be translated into 'Fixes bug introduced in destination/123456', provided" + " that a change with the proper label was found - the message remains unchanged " + "otherwise.")
public ReferenceMigrator mapReferences(String originPattern, String destinationFormat, // <String, String>
Dict<?, ?> groups, // <String>
Sequence<?> labels, StarlarkThread thread) throws EvalException {
Map<String, String> groupsMap = Dict.cast(groups, String.class, String.class, "regex_groups");
check(groupsMap.containsKey("before_ref") && (groupsMap.size() != 2 || groupsMap.containsKey("after_ref")) && groupsMap.size() <= 2, "Invalid 'regex_groups' - Should only contain 'before_ref' and " + "optionally 'after_ref'. Was: %s.", groupsMap.keySet());
Pattern beforePattern;
Pattern afterPattern = null;
try {
beforePattern = Pattern.compile(groupsMap.get("before_ref"));
} catch (java.util.regex.PatternSyntaxException exception) {
throw Starlark.errorf("Invalid before_ref regex '%s'.", groupsMap.get("before_ref"));
}
if (groupsMap.containsKey("after_ref")) {
try {
afterPattern = Pattern.compile(groupsMap.get("after_ref"));
} catch (java.util.regex.PatternSyntaxException exception) {
throw Starlark.errorf("Invalid after_ref regex '%s'.", groupsMap.get("after_ref"));
}
}
return ReferenceMigrator.create(originPattern, destinationFormat, beforePattern, afterPattern, ImmutableList.copyOf(SkylarkUtil.convertStringList(labels, "labels")), thread.getCallerLocation());
}
use of com.google.copybara.doc.annotations.Example in project copybara by google.
the class PatchModule method quiltApply.
@SuppressWarnings("unused")
@StarlarkMethod(name = "quilt_apply", doc = "A transformation that applies and updates patch files using Quilt. Compared to" + " `patch.apply`, this transformation supports updating the content of patch files" + " if they can be successfully applied with fuzz. The patch files must be included" + " in the destination_files glob in order to get updated. Underneath, Copybara" + " runs `quilt import; quilt push; quilt refresh` for each patch file in the" + " `series` file in order. Currently, all patch files and the `series` file must" + " reside in a \"patches\" sub-directory under the root directory containing the" + " migrated code. This means it has the limitation that the migrated code itself" + " cannot contain a directory with the name \"patches\".", parameters = { @Param(name = "series", named = true, positional = false, doc = "A file which contains a list of patches to apply. It is similar to the `series`" + " parameter in `patch.apply` transformation, and is required for Quilt." + " Patches listed in this file will be applied relative to the checkout dir," + " and the leading path component is stripped via the `-p1` flag. Currently" + " this file should be the `patches/series` file in the root directory" + " of the migrated code.") }, useStarlarkThread = true)
@Example(title = "Workflow to apply and update patches", before = "Suppose the destination repository's directory structure looks like:\n" + "```\n" + "source_root/BUILD\n" + "source_root/copy.bara.sky\n" + "source_root/migrated_file1\n" + "source_root/migrated_file2\n" + "source_root/patches/series\n" + "source_root/patches/patch1.patch\n" + "```\n" + "Then the transformations in `source_root/copy.bara.sky` should look like:", code = "[\n" + " patch.quilt_apply(series = \"patches/series\"),\n" + " core.move(\"\", \"source_root\"),\n" + "]", after = "In this example, `patch1.patch` is applied to `migrated_file1` and/or `migrated_file2`." + " `patch1.patch` itself will be updated during the migration if it is applied with" + " fuzz.")
@UsesFlags(PatchingOptions.class)
public QuiltTransformation quiltApply(String series, StarlarkThread thread) throws EvalException {
ImmutableList.Builder<ConfigFile> builder = ImmutableList.builder();
ConfigFile seriesFile = parseSeries(series, builder);
return new QuiltTransformation(seriesFile, builder.build(), patchingOptions, /*reverse=*/
false, thread.getCallerLocation());
}
Aggregations