@@ -0,0 +1,3 | |||||
|
1 | { | |||
|
2 | "java.configuration.updateBuildConfiguration": "automatic" | |||
|
3 | } No newline at end of file |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
@@ -0,0 +1,5 | |||||
|
1 | distributionBase=GRADLE_USER_HOME | |||
|
2 | distributionPath=wrapper/dists | |||
|
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip | |||
|
4 | zipStoreBase=GRADLE_USER_HOME | |||
|
5 | zipStorePath=wrapper/dists |
@@ -0,0 +1,120 | |||||
|
1 | # Mercurial build integration | |||
|
2 | ||||
|
3 | ## SYNOPSIS | |||
|
4 | ||||
|
5 | ```groovy | |||
|
6 | ||||
|
7 | plugins { | |||
|
8 | id 'org.implab.gradle-mercurial' version '1.0' | |||
|
9 | } | |||
|
10 | ||||
|
11 | mercurial { | |||
|
12 | releaseBookmark = 'prod' | |||
|
13 | ||||
|
14 | preReleasePolicy { it | |||
|
15 | // this is the default behaviour | |||
|
16 | .addPatch(1) | |||
|
17 | .withPreRelease('snapshot') | |||
|
18 | .withMeta('changeset') | |||
|
19 | } | |||
|
20 | ||||
|
21 | // get version from repository and apply it to the project | |||
|
22 | applyVersioningPolicy() | |||
|
23 | } | |||
|
24 | ||||
|
25 | ``` | |||
|
26 | ||||
|
27 | ## DESCRIPTION | |||
|
28 | ||||
|
29 | ### `semver(versionString)` | |||
|
30 | ||||
|
31 | Parses the specified version string and returns the semantic version object | |||
|
32 | ||||
|
33 | ### `mercurial(Closure configure)` | |||
|
34 | ||||
|
35 | The extension added by the plugin to the project. Apply this plugin to the | |||
|
36 | root project and use the `mercurial { ... }` section to configure the | |||
|
37 | versioning. | |||
|
38 | ||||
|
39 | See the description below for more details about settings. | |||
|
40 | ||||
|
41 | #### `hgCmd` | |||
|
42 | ||||
|
43 | The command which will be executed to perform the mercurial commands. | |||
|
44 | The default value is `hg`. | |||
|
45 | ||||
|
46 | #### `outputCharset` | |||
|
47 | ||||
|
48 | The charset for the `hgCmd` output, this property defaults | |||
|
49 | to the default charset of the operating system. | |||
|
50 | ||||
|
51 | #### `hg(...args)` | |||
|
52 | ||||
|
53 | Executes the mercurial command, returns the command output as text. | |||
|
54 | ||||
|
55 | #### `workspaceInfo` (read-only) | |||
|
56 | ||||
|
57 | Returns the information about current workspace, see description | |||
|
58 | below for details. | |||
|
59 | ||||
|
60 | #### `workspaceVersion` | |||
|
61 | ||||
|
62 | Returns the semantic version obtained from the repository. Querying | |||
|
63 | this property will lead querying the workspace info. | |||
|
64 | ||||
|
65 | #### `applyVersioningPolicy()` | |||
|
66 | ||||
|
67 | Reads the workspace information and sets the version of the project | |||
|
68 | according to settings. | |||
|
69 | ||||
|
70 | If the version was specified using properties, then the specified | |||
|
71 | version will take preceding over the calculated one. | |||
|
72 | ||||
|
73 | #### `preReleasePolicy(Closure<SemVersion> config)` | |||
|
74 | ||||
|
75 | The closure which is used to calculate the version of the project | |||
|
76 | when the current commit isn't marked with a version tag. | |||
|
77 | ||||
|
78 | The default behaviour is to increment the patch version and | |||
|
79 | to set the pre-release suffix to `'snapshot'`. | |||
|
80 | ||||
|
81 | ### `WorkspaceInfo` | |||
|
82 | ||||
|
83 | This class encapsulates information about the current workspace. | |||
|
84 | All properties are read-only. | |||
|
85 | ||||
|
86 | #### `versionTag` | |||
|
87 | ||||
|
88 | The original version tag from the repository before parsing. | |||
|
89 | ||||
|
90 | #### `changeSet` | |||
|
91 | ||||
|
92 | The changeset id of the current workspace. | |||
|
93 | ||||
|
94 | #### `versionDistance` | |||
|
95 | ||||
|
96 | The distance in commits to the versionTag | |||
|
97 | ||||
|
98 | #### `branch` | |||
|
99 | ||||
|
100 | The name of the current sources branch. | |||
|
101 | ||||
|
102 | #### `isDirty` | |||
|
103 | ||||
|
104 | This flag indicates uncommited changes to the workspace. This flag is useful | |||
|
105 | to control some pipelines which run locally on developer machines. | |||
|
106 | ||||
|
107 | ## TASKS | |||
|
108 | ||||
|
109 | ### `release` | |||
|
110 | ||||
|
111 | Marks this commit with current version and pre-release suffix removed and | |||
|
112 | moves the `release` bookmark to it. | |||
|
113 | ||||
|
114 | ### `staging` | |||
|
115 | ||||
|
116 | Marks this commit with current version and moves the `staging` bookmark to it. | |||
|
117 | ||||
|
118 | ### `printVersion` | |||
|
119 | ||||
|
120 | Prints the current version. |
@@ -1,17 +1,26 | |||||
1 | plugins { |
|
1 | plugins { | |
2 | id "java-gradle-plugin" |
|
2 | id "java-gradle-plugin" | |
|
3 | id "com.gradle.plugin-publish" version "0.16.0" | |||
3 | } |
|
4 | } | |
4 |
|
5 | |||
5 |
|
||||
6 | repositories { |
|
6 | repositories { | |
7 | mavenCentral() |
|
7 | mavenCentral() | |
8 | } |
|
8 | } | |
9 |
|
9 | |||
10 | gradlePlugin { |
|
10 | gradlePlugin { | |
11 | plugins { |
|
11 | plugins { | |
12 |
|
|
12 | mercurialPlugin { | |
13 | id = 'org.implab.gradle-mercurial' |
|
13 | id = 'org.implab.gradle-mercurial' | |
14 | implementationClass = 'org.implab.gradle.mercurial.MercurialPlugin' |
|
14 | implementationClass = 'org.implab.gradle.mercurial.MercurialPlugin' | |
|
15 | displayName = "Integrates mercurial into the build script" | |||
|
16 | description = 'Automatically calculates version using tags. Simple wrapper around cli.' | |||
15 | } |
|
17 | } | |
16 | } |
|
18 | } | |
17 | } |
|
19 | } | |
|
20 | ||||
|
21 | pluginBundle { | |||
|
22 | website = 'https://code.implab.org/implab/gradle-mercurial-plugin' | |||
|
23 | vcsUrl = 'https://code.implab.org/implab/gradle-mercurial-plugin' | |||
|
24 | ||||
|
25 | tags = ['hg', 'mercurial'] | |||
|
26 | } |
@@ -1,108 +1,114 | |||||
1 | package org.implab.gradle; |
|
1 | package org.implab.gradle; | |
2 |
|
2 | |||
3 | import java.io.ByteArrayOutputStream; |
|
3 | import java.io.ByteArrayOutputStream; | |
4 | import java.io.Closeable; |
|
4 | import java.io.Closeable; | |
5 | import java.io.File; |
|
5 | import java.io.File; | |
6 | import java.io.FileOutputStream; |
|
6 | import java.io.FileOutputStream; | |
7 | import java.io.IOException; |
|
7 | import java.io.IOException; | |
8 | import java.io.InputStream; |
|
8 | import java.io.InputStream; | |
9 | import java.io.OutputStream; |
|
9 | import java.io.OutputStream; | |
10 | import java.util.List; |
|
10 | import java.util.List; | |
11 | import java.util.Scanner; |
|
11 | import java.util.Scanner; | |
12 |
|
12 | |||
13 | import org.gradle.api.Action; |
|
13 | import org.gradle.api.Action; | |
14 | import groovy.json.JsonGenerator; |
|
14 | import groovy.json.JsonGenerator; | |
15 | import groovy.json.JsonOutput; |
|
15 | import groovy.json.JsonOutput; | |
16 | import groovy.json.JsonGenerator.Converter; |
|
16 | import groovy.json.JsonGenerator.Converter; | |
17 | import groovy.lang.Closure; |
|
17 | import groovy.lang.Closure; | |
18 |
|
18 | |||
19 | public final class Utils { |
|
19 | public final class Utils { | |
20 | public static void redirectIO(final InputStream src, final Action<String> consumer) { |
|
20 | public static void redirectIO(final InputStream src, final Action<String> consumer) { | |
21 |
|
|
21 | new Thread(() -> { | |
22 |
|
|
22 | try (Scanner sc = new Scanner(src)) { | |
23 |
|
|
23 | while (sc.hasNextLine()) { | |
24 |
|
|
24 | consumer.execute(sc.nextLine()); | |
25 | } |
|
25 | } | |
26 | } |
|
26 | } | |
27 |
|
|
27 | }).start(); | |
28 | } |
|
28 | } | |
29 |
|
29 | |||
30 |
public static String execCmd(List<String> args, String charset) |
|
30 | public static String execCmd(List<String> args, String charset) { | |
31 | if (args == null || args.size() == 0) |
|
31 | if (args == null || args.size() == 0) | |
32 | throw new IllegalArgumentException(); |
|
32 | throw new IllegalArgumentException(); | |
33 |
|
33 | |||
34 | ProcessBuilder builder = new ProcessBuilder(args); |
|
34 | ProcessBuilder builder = new ProcessBuilder(args); | |
35 |
|
35 | |||
36 |
Process p |
|
36 | Process p; | |
|
37 | try { | |||
|
38 | p = builder.start(); | |||
37 |
|
39 | |||
38 | String output = readAll(p.getInputStream(), charset); |
|
40 | String output = readAll(p.getInputStream(), charset); | |
39 |
|
41 | |||
40 | int code = p.waitFor(); |
|
42 | int code = p.waitFor(); | |
41 | if (code != 0) |
|
43 | if (code != 0) | |
42 | throw new Exception(String.format("The process `%s` failed with code: %s", args.get(0), code)); |
|
44 | throw new RuntimeException(String.format("The process `%s` failed with code: %s", args.get(0), code)); | |
43 |
|
45 | |||
44 | return output; |
|
46 | return output; | |
|
47 | } catch (IOException | InterruptedException e) { | |||
|
48 | throw new RuntimeException(String.format("Failed to execute `%s`", args.get(0)), e); | |||
|
49 | } | |||
45 |
|
50 | |||
46 | } |
|
51 | } | |
47 |
|
52 | |||
48 | public static void redirectIO(final InputStream src, final File file) { |
|
53 | public static void redirectIO(final InputStream src, final File file) { | |
49 |
|
|
54 | new Thread(() -> { | |
50 | try (OutputStream out = new FileOutputStream(file)) { |
|
55 | try (OutputStream out = new FileOutputStream(file)) { | |
51 | src.transferTo(out); |
|
56 | src.transferTo(out); | |
52 | } catch(Exception e) { |
|
57 | } catch (Exception e) { | |
53 | // silence! |
|
58 | // silence! | |
54 | } |
|
59 | } | |
55 |
|
|
60 | }).start(); | |
56 | } |
|
61 | } | |
57 |
|
62 | |||
58 | public static String readAll(final InputStream src) throws IOException { |
|
63 | public static String readAll(final InputStream src) throws IOException { | |
59 | ByteArrayOutputStream out = new ByteArrayOutputStream(); |
|
64 | ByteArrayOutputStream out = new ByteArrayOutputStream(); | |
60 | src.transferTo(out); |
|
65 | src.transferTo(out); | |
61 | return out.toString(); |
|
66 | return out.toString(); | |
62 | } |
|
67 | } | |
63 |
|
68 | |||
64 | public static String readAll(final InputStream src, String charset) throws IOException { |
|
69 | public static String readAll(final InputStream src, String charset) throws IOException { | |
65 | ByteArrayOutputStream out = new ByteArrayOutputStream(); |
|
70 | ByteArrayOutputStream out = new ByteArrayOutputStream(); | |
66 | src.transferTo(out); |
|
71 | src.transferTo(out); | |
67 | return out.toString(charset); |
|
72 | return out.toString(charset); | |
68 | } |
|
73 | } | |
69 |
|
74 | |||
70 |
|
|
75 | public static JsonGenerator createDefaultJsonGenerator() { | |
71 | return new JsonGenerator.Options() |
|
76 | return new JsonGenerator.Options() | |
72 | .excludeNulls() |
|
77 | .excludeNulls() | |
73 | .addConverter(new Converter() { |
|
78 | .addConverter(new Converter() { | |
74 | public boolean handles(Class<?> type) { |
|
79 | public boolean handles(Class<?> type) { | |
75 | return (File.class == type); |
|
80 | return (File.class == type); | |
76 | } |
|
81 | } | |
|
82 | ||||
77 | public Object convert(Object value, String key) { |
|
83 | public Object convert(Object value, String key) { | |
78 | return ((File)value).getPath(); |
|
84 | return ((File) value).getPath(); | |
79 | } |
|
85 | } | |
80 | }) |
|
86 | }) | |
81 | .build(); |
|
87 | .build(); | |
82 | } |
|
88 | } | |
83 |
|
89 | |||
84 | public static void closeSilent(Closeable handle) { |
|
90 | public static void closeSilent(Closeable handle) { | |
85 | try { |
|
91 | try { | |
86 | handle.close(); |
|
92 | handle.close(); | |
87 | } catch(Exception e) { |
|
93 | } catch (Exception e) { | |
88 | // silence! |
|
94 | // silence! | |
89 | } |
|
95 | } | |
90 | } |
|
96 | } | |
91 |
|
97 | |||
92 | public static String toJsonPretty(Object value) { |
|
98 | public static String toJsonPretty(Object value) { | |
93 | return JsonOutput.prettyPrint(createDefaultJsonGenerator().toJson(value)); |
|
99 | return JsonOutput.prettyPrint(createDefaultJsonGenerator().toJson(value)); | |
94 | } |
|
100 | } | |
95 |
|
101 | |||
96 | public static boolean isNullOrEmptyString(String value) { |
|
102 | public static boolean isNullOrEmptyString(String value) { | |
97 | return (value == null || value.length() == 0); |
|
103 | return (value == null || value.length() == 0); | |
98 | } |
|
104 | } | |
99 |
|
105 | |||
100 | public static <T> Action<T> wrapClosure(Closure<?> closure) { |
|
106 | public static <T> Action<T> wrapClosure(Closure<?> closure) { | |
101 | return x -> { |
|
107 | return x -> { | |
102 | closure.setDelegate(x); |
|
108 | closure.setDelegate(x); | |
103 | closure.setResolveStrategy(Closure.DELEGATE_FIRST); |
|
109 | closure.setResolveStrategy(Closure.DELEGATE_FIRST); | |
104 | closure.call(x); |
|
110 | closure.call(x); | |
105 | }; |
|
111 | }; | |
106 | } |
|
112 | } | |
107 |
|
113 | |||
108 | } |
|
114 | } |
@@ -1,115 +1,172 | |||||
1 | package org.implab.gradle.mercurial; |
|
1 | package org.implab.gradle.mercurial; | |
2 |
|
2 | |||
3 | import java.nio.charset.Charset; |
|
3 | import java.nio.charset.Charset; | |
4 | import java.util.ArrayList; |
|
4 | import java.util.ArrayList; | |
5 | import java.util.Collections; |
|
5 | import java.util.Collections; | |
6 | import java.util.List; |
|
6 | import java.util.List; | |
7 | import java.util.Objects; |
|
7 | import java.util.Objects; | |
8 | import java.util.Optional; |
|
8 | import java.util.Optional; | |
|
9 | import java.util.function.Function; | |||
9 | import java.util.regex.Matcher; |
|
10 | import java.util.regex.Matcher; | |
10 | import java.util.regex.Pattern; |
|
11 | import java.util.regex.Pattern; | |
11 |
|
12 | |||
12 | import org.gradle.api.Project; |
|
13 | import org.gradle.api.Project; | |
13 | import org.implab.gradle.Utils; |
|
14 | import org.implab.gradle.Utils; | |
14 |
|
15 | |||
|
16 | import groovy.lang.Closure; | |||
|
17 | ||||
15 | public class MercurialExtension { |
|
18 | public class MercurialExtension { | |
16 | private static final String COMMIT_INFO_TEMPLATE = "{latesttag('re:^v') % '{ifeq(tag,'null','',tag)}:{distance}'}:{branch}:{node|short}"; |
|
19 | private static final String COMMIT_INFO_TEMPLATE = "{latesttag('re:^v') % '{ifeq(tag,'null','',tag)}:{distance}'}:{branch}:{node|short}"; | |
17 |
|
20 | |||
18 | private static final Pattern versionPattern = Pattern.compile("^(?:v[\\-_\\.]?)?(.*)"); |
|
21 | private static final Pattern versionPattern = Pattern.compile("^(?:v[\\-_\\.]?)?(.*)"); | |
19 |
|
22 | |||
20 | private final Project project; |
|
23 | private final Project project; | |
21 |
|
24 | |||
22 | private Charset outputCharset = Charset.defaultCharset(); |
|
25 | private Charset outputCharset = Charset.defaultCharset(); | |
23 |
|
26 | |||
24 | private WorkspaceInfo workspaceInfo; |
|
27 | private WorkspaceInfo workspaceInfo; | |
25 |
|
28 | |||
26 | private String hgCmd = "hg"; |
|
29 | private String hgCmd = "hg"; | |
27 |
|
30 | |||
|
31 | private String stagingBookmark = "staging"; | |||
|
32 | ||||
|
33 | private String releaseBookmark = "prod"; | |||
|
34 | ||||
28 | private SemVersion defaultWorkspaceVersion = new SemVersion(0, 0, 1, "dev", null); |
|
35 | private SemVersion defaultWorkspaceVersion = new SemVersion(0, 0, 1, "dev", null); | |
29 |
|
36 | |||
|
37 | private Function<SemVersion, SemVersion> preReleasePolicy; | |||
|
38 | ||||
30 | public MercurialExtension(Project project) { |
|
39 | public MercurialExtension(Project project) { | |
31 | Objects.requireNonNull(project); |
|
40 | Objects.requireNonNull(project); | |
32 |
|
41 | |||
33 | this.project = project; |
|
42 | this.project = project; | |
34 | } |
|
43 | } | |
35 |
|
44 | |||
36 |
public String hg(String... args) |
|
45 | public String hg(String... args) { | |
37 | List<String> commandLine = new ArrayList<>(); |
|
46 | List<String> commandLine = new ArrayList<>(); | |
38 | commandLine.add(hgCmd); |
|
47 | commandLine.add(hgCmd); | |
39 | Collections.addAll(commandLine, args); |
|
48 | Collections.addAll(commandLine, args); | |
40 |
|
49 | |||
41 | return Utils.execCmd(commandLine, outputCharset.name()); |
|
50 | return Utils.execCmd(commandLine, outputCharset.name()); | |
42 | } |
|
51 | } | |
43 |
|
52 | |||
|
53 | public String getReleaseBookmark() { | |||
|
54 | return releaseBookmark; | |||
|
55 | } | |||
|
56 | ||||
|
57 | public void setReleaseBookmark(String value) { | |||
|
58 | if(value == null) | |||
|
59 | throw new IllegalArgumentException(); | |||
|
60 | releaseBookmark = value; | |||
|
61 | } | |||
|
62 | ||||
|
63 | public String getStagingBookmark() { | |||
|
64 | return stagingBookmark; | |||
|
65 | } | |||
|
66 | ||||
|
67 | public void setStagingBookmark(String value) { | |||
|
68 | if(value == null) | |||
|
69 | throw new IllegalArgumentException(); | |||
|
70 | stagingBookmark = value; | |||
|
71 | } | |||
|
72 | ||||
44 | public Charset getOutputCharset() { |
|
73 | public Charset getOutputCharset() { | |
45 | return outputCharset; |
|
74 | return outputCharset; | |
46 | } |
|
75 | } | |
47 |
|
76 | |||
48 | public void setOutputCharset(Charset outputCharset) { |
|
77 | public void setOutputCharset(Charset outputCharset) { | |
49 | this.outputCharset = Optional.ofNullable(outputCharset).orElseGet(Charset::defaultCharset); |
|
78 | this.outputCharset = Optional.ofNullable(outputCharset).orElseGet(Charset::defaultCharset); | |
50 | } |
|
79 | } | |
51 |
|
80 | |||
52 | public void setOutputCharset(String outputCharset) { |
|
81 | public void setOutputCharset(String outputCharset) { | |
53 | this.outputCharset = Optional.ofNullable(outputCharset).map(x -> Charset.forName(x)) |
|
82 | this.outputCharset = Optional.ofNullable(outputCharset).map(x -> Charset.forName(x)) | |
54 | .orElseGet(Charset::defaultCharset); |
|
83 | .orElseGet(Charset::defaultCharset); | |
55 | } |
|
84 | } | |
56 |
|
85 | |||
57 | public String getHgCmd() { |
|
86 | public String getHgCmd() { | |
58 | return hgCmd; |
|
87 | return hgCmd; | |
59 | } |
|
88 | } | |
60 |
|
89 | |||
61 | public void setHgCmd(String hgCmd) { |
|
90 | public void setHgCmd(String hgCmd) { | |
62 | this.hgCmd = hgCmd; |
|
91 | this.hgCmd = hgCmd; | |
63 | } |
|
92 | } | |
64 |
|
93 | |||
65 |
public WorkspaceInfo getWorkspaceInfo() |
|
94 | public WorkspaceInfo getWorkspaceInfo() { | |
66 | if (workspaceInfo == null) |
|
95 | if (workspaceInfo == null) | |
67 | workspaceInfo = loadWorkspaceInfo(); |
|
96 | workspaceInfo = loadWorkspaceInfo(); | |
68 | return workspaceInfo; |
|
97 | return workspaceInfo; | |
69 | } |
|
98 | } | |
70 |
|
99 | |||
71 |
public SemVersion getWorkspaceVersion() |
|
100 | public SemVersion getWorkspaceVersion() { | |
72 | return tryParseVersion(getWorkspaceInfo().getVersionTag()).orElse(defaultWorkspaceVersion); |
|
101 | return tryParseVersion(getWorkspaceInfo().getVersionTag()).orElse(defaultWorkspaceVersion); | |
73 | } |
|
102 | } | |
74 |
|
103 | |||
75 | public void applyVersioningPolicy() throws Exception { |
|
104 | private SemVersion defaultPreReleasePolicy(SemVersion version) { | |
76 | Object version = project.getVersion(); |
|
|||
77 | if (version == null || version.toString().isBlank() || version.toString().equalsIgnoreCase(Project.DEFAULT_VERSION)) { |
|
|||
78 | int distance = getWorkspaceInfo().getVersionDistance(); |
|
|||
79 |
|
|
105 | String changeset = getWorkspaceInfo().getChangeset(); | |
80 | project.setVersion( |
|
106 | return version.addPatch(1).withPreRelease("snapshot").withMeta(changeset); | |
81 | distance> 0 ? |
|
107 | } | |
82 | getWorkspaceVersion().addPatch(distance).suffix("snapshot").meta(changeset) : |
|
108 | ||
83 | getWorkspaceVersion() |
|
109 | public void preReleasePolicy(Closure<SemVersion> policy) { | |
84 | ); |
|
110 | if (policy == null) | |
|
111 | throw new IllegalArgumentException(); | |||
|
112 | ||||
|
113 | this.preReleasePolicy = x -> { | |||
|
114 | policy.setDelegate(getWorkspaceInfo()); | |||
|
115 | policy.setResolveStrategy(Closure.DELEGATE_FIRST); | |||
|
116 | return policy.call(x); | |||
|
117 | }; | |||
|
118 | } | |||
|
119 | ||||
|
120 | public void preReleasePolicy(Function<SemVersion, SemVersion> policy) { | |||
|
121 | if (policy == null) | |||
|
122 | throw new IllegalArgumentException(); | |||
|
123 | this.preReleasePolicy = policy; | |||
|
124 | } | |||
|
125 | ||||
|
126 | public void applyVersioningPolicy() { | |||
|
127 | Object version = project.getVersion(); | |||
|
128 | if (version == null || version.toString().isBlank() | |||
|
129 | || version.toString().equalsIgnoreCase(Project.DEFAULT_VERSION)) { | |||
|
130 | // if the version isn't specified | |||
|
131 | int distance = getWorkspaceInfo().getVersionDistance(); | |||
|
132 | ||||
|
133 | // the current workspace is not tagged with the version | |||
|
134 | if (distance > 0) { | |||
|
135 | SemVersion preReleaseVersion = Optional.ofNullable(preReleasePolicy) | |||
|
136 | .orElse(this::defaultPreReleasePolicy) | |||
|
137 | .apply(getWorkspaceVersion()); | |||
|
138 | ||||
|
139 | project.setVersion(preReleaseVersion); | |||
|
140 | } else { | |||
|
141 | project.setVersion(getWorkspaceVersion()); | |||
|
142 | } | |||
85 | } else { |
|
143 | } else { | |
86 | project.setVersion(SemVersion.toSemVersion(version, false)); |
|
144 | project.setVersion(SemVersion.toSemVersion(version, false)); | |
87 | } |
|
145 | } | |
88 | } |
|
146 | } | |
89 |
|
147 | |||
90 |
String[] queryLogInfo() |
|
148 | String[] queryLogInfo() { | |
91 | return hg("log", "-r", ".", "--template", COMMIT_INFO_TEMPLATE).split(":"); |
|
149 | return hg("log", "-r", ".", "--template", COMMIT_INFO_TEMPLATE).split(":"); | |
92 | } |
|
150 | } | |
93 |
|
151 | |||
94 |
WorkspaceInfo loadWorkspaceInfo() |
|
152 | WorkspaceInfo loadWorkspaceInfo() { | |
95 | boolean isDirty = checkIsDirty(); |
|
153 | boolean isDirty = checkIsDirty(); | |
96 | String[] info = queryLogInfo(); |
|
154 | String[] info = queryLogInfo(); | |
97 | return new WorkspaceInfo(info[0], Integer.parseInt(info[1]), info[2], info[3], isDirty); |
|
155 | return new WorkspaceInfo(info[0], Integer.parseInt(info[1]), info[2], info[3], isDirty); | |
98 | } |
|
156 | } | |
99 |
|
157 | |||
100 |
boolean checkIsDirty() |
|
158 | boolean checkIsDirty() { | |
101 | return !hg("status", "-mard").isBlank(); |
|
159 | return !hg("status", "-mard").isBlank(); | |
102 | } |
|
160 | } | |
103 |
|
161 | |||
104 | Optional<SemVersion> tryParseVersion(String version) { |
|
162 | Optional<SemVersion> tryParseVersion(String version) { | |
105 | if (version == null) |
|
163 | if (version == null) | |
106 | return Optional.empty(); |
|
164 | return Optional.empty(); | |
107 |
|
165 | |||
108 | Matcher m = versionPattern.matcher(version); |
|
166 | Matcher m = versionPattern.matcher(version); | |
109 | boolean isMatch = m.matches(); |
|
167 | boolean isMatch = m.matches(); | |
110 |
|
168 | |||
111 | return isMatch ? SemVersion.tryParseLax(m.group(1)) : Optional.empty(); |
|
169 | return isMatch ? SemVersion.tryParseLax(m.group(1)) : Optional.empty(); | |
112 | } |
|
170 | } | |
113 |
|
171 | |||
114 |
|
||||
115 | } |
|
172 | } |
@@ -1,85 +1,86 | |||||
1 | package org.implab.gradle.mercurial; |
|
1 | package org.implab.gradle.mercurial; | |
2 |
|
2 | |||
3 | import org.codehaus.groovy.runtime.MethodClosure; |
|
3 | import org.codehaus.groovy.runtime.MethodClosure; | |
4 | import org.gradle.api.Plugin; |
|
4 | import org.gradle.api.Plugin; | |
5 | import org.gradle.api.Project; |
|
5 | import org.gradle.api.Project; | |
6 | import org.gradle.api.plugins.ExtraPropertiesExtension; |
|
6 | import org.gradle.api.plugins.ExtraPropertiesExtension; | |
7 | import org.gradle.api.tasks.TaskExecutionException; |
|
7 | import org.gradle.api.tasks.TaskExecutionException; | |
8 | import org.gradle.api.tasks.TaskProvider; |
|
8 | import org.gradle.api.tasks.TaskProvider; | |
9 | import org.implab.gradle.mercurial.tasks.HgBookmark; |
|
9 | import org.implab.gradle.mercurial.tasks.HgBookmark; | |
10 | import org.implab.gradle.mercurial.tasks.HgTag; |
|
10 | import org.implab.gradle.mercurial.tasks.HgTag; | |
11 | import org.implab.gradle.mercurial.tasks.HgTask; |
|
11 | import org.implab.gradle.mercurial.tasks.HgTask; | |
12 |
|
12 | |||
13 | public class MercurialPlugin implements Plugin<Project> { |
|
13 | public class MercurialPlugin implements Plugin<Project> { | |
14 |
|
14 | |||
15 | public final String MERCURIAL_EXTENSION_NAME = "mercurial"; |
|
15 | public final String MERCURIAL_EXTENSION_NAME = "mercurial"; | |
16 |
|
16 | |||
17 | private MercurialExtension mercurialExtension; |
|
17 | private MercurialExtension mercurialExtension; | |
18 |
|
18 | |||
19 | @Override |
|
19 | @Override | |
20 | public void apply(Project project) { |
|
20 | public void apply(Project project) { | |
21 |
|
21 | |||
22 | mercurialExtension = new MercurialExtension(project); |
|
22 | mercurialExtension = new MercurialExtension(project); | |
23 |
|
23 | |||
24 | project.getExtensions().add(MERCURIAL_EXTENSION_NAME, mercurialExtension); |
|
24 | project.getExtensions().add(MERCURIAL_EXTENSION_NAME, mercurialExtension); | |
25 |
|
25 | |||
26 | ExtraPropertiesExtension extras = project.getExtensions().getExtraProperties(); |
|
26 | ExtraPropertiesExtension extras = project.getExtensions().getExtraProperties(); | |
27 | extras.set(HgTask.class.getSimpleName(), HgTask.class); |
|
27 | extras.set(HgTask.class.getSimpleName(), HgTask.class); | |
28 | extras.set("semver", new MethodClosure(SemVersion.class, "toSemVersion")); |
|
28 | extras.set("semver", new MethodClosure(SemVersion.class, "toSemVersion")); | |
29 |
|
29 | |||
30 | project.getTasks().register("printVersion", t -> { |
|
30 | project.getTasks().register("printVersion", t -> { | |
31 | t.doLast(t2 -> { |
|
31 | t.doLast(t2 -> { | |
|
32 | t2.getLogger().quiet("workspace: {}", mercurialExtension.getWorkspaceInfo()); | |||
32 | t2.getLogger().quiet("version: {}", project.getVersion()); |
|
33 | t2.getLogger().quiet("version: {}", project.getVersion()); | |
33 | }); |
|
34 | }); | |
34 | }); |
|
35 | }); | |
35 |
|
36 | |||
36 | TaskProvider<HgBookmark> hgBookmarkTask = project.getTasks().register("hgBookmark", HgBookmark.class, t -> { |
|
37 | TaskProvider<HgBookmark> hgBookmarkTask = project.getTasks().register("hgBookmark", HgBookmark.class, t -> { | |
37 | t.getInactive().set(true); |
|
38 | t.getInactive().set(true); | |
38 | t.getForce().set(true); |
|
39 | t.getForce().set(true); | |
39 | }); |
|
40 | }); | |
40 |
|
41 | |||
41 | TaskProvider<HgTag> hgTagTask = project.getTasks().register("hgTag", HgTag.class, t -> { |
|
42 | TaskProvider<HgTag> hgTagTask = project.getTasks().register("hgTag", HgTag.class, t -> { | |
42 | t.mustRunAfter(hgBookmarkTask); |
|
43 | t.mustRunAfter(hgBookmarkTask); | |
43 | }); |
|
44 | }); | |
44 |
|
45 | |||
45 | project.getTasks().register("release", t -> { |
|
46 | project.getTasks().register("release", t -> { | |
46 | t.finalizedBy(hgBookmarkTask, hgTagTask); |
|
47 | t.finalizedBy(hgBookmarkTask, hgTagTask); | |
47 | t.doLast(self -> { |
|
48 | t.doLast(self -> { | |
48 | try { |
|
49 | try { | |
49 | if (mercurialExtension.checkIsDirty()) |
|
50 | if (mercurialExtension.checkIsDirty()) | |
50 | throw new Exception("The workspace is dirty, you need to commit changes first"); |
|
51 | throw new Exception("The workspace is dirty, you need to commit changes first"); | |
51 |
|
52 | |||
52 | SemVersion version = (SemVersion) project.getVersion(); |
|
53 | SemVersion version = (SemVersion) project.getVersion(); | |
53 |
SemVersion nextVersion = version. |
|
54 | SemVersion nextVersion = version.withNoSuffix(); | |
54 |
|
55 | |||
55 |
self.getLogger().quiet(" |
|
56 | self.getLogger().quiet("{} {} -> {}", mercurialExtension.getReleaseBookmark(), version, nextVersion); | |
56 |
|
57 | |||
57 |
hgBookmarkTask.get().getBookmarks().add( |
|
58 | hgBookmarkTask.get().getBookmarks().add(mercurialExtension.getReleaseBookmark()); | |
58 | hgTagTask.get().getTags().add("v" + nextVersion.toString()); |
|
59 | hgTagTask.get().getTags().add("v" + nextVersion.toString()); | |
59 | } catch (Exception e) { |
|
60 | } catch (Exception e) { | |
60 | throw new TaskExecutionException(self, e); |
|
61 | throw new TaskExecutionException(self, e); | |
61 | } |
|
62 | } | |
62 | }); |
|
63 | }); | |
63 | }); |
|
64 | }); | |
64 |
|
65 | |||
65 | project.getTasks().register("staging", t -> { |
|
66 | project.getTasks().register("staging", t -> { | |
66 | t.finalizedBy(hgBookmarkTask, hgTagTask); |
|
67 | t.finalizedBy(hgBookmarkTask, hgTagTask); | |
67 | t.doLast(self -> { |
|
68 | t.doLast(self -> { | |
68 | try { |
|
69 | try { | |
69 | if (mercurialExtension.checkIsDirty()) |
|
70 | if (mercurialExtension.checkIsDirty()) | |
70 | throw new Exception("The workspace is dirty, you need to commit changes first"); |
|
71 | throw new Exception("The workspace is dirty, you need to commit changes first"); | |
71 |
|
72 | |||
72 | SemVersion version = (SemVersion) project.getVersion(); |
|
73 | SemVersion version = (SemVersion) project.getVersion(); | |
73 |
SemVersion nextVersion = version. |
|
74 | SemVersion nextVersion = version.withNoSuffix().withPreRelease("rc"); | |
74 |
|
75 | |||
75 |
self.getLogger().quiet(" |
|
76 | self.getLogger().quiet("{} {} -> {}", mercurialExtension.getStagingBookmark(), version, nextVersion); | |
76 |
|
77 | |||
77 |
hgBookmarkTask.get().getBookmarks().add( |
|
78 | hgBookmarkTask.get().getBookmarks().add(mercurialExtension.getStagingBookmark()); | |
78 | hgTagTask.get().getTags().add("v" + nextVersion.toString()); |
|
79 | hgTagTask.get().getTags().add("v" + nextVersion.toString()); | |
79 | } catch (Exception e) { |
|
80 | } catch (Exception e) { | |
80 | throw new TaskExecutionException(self, e); |
|
81 | throw new TaskExecutionException(self, e); | |
81 | } |
|
82 | } | |
82 | }); |
|
83 | }); | |
83 | }); |
|
84 | }); | |
84 | } |
|
85 | } | |
85 | } |
|
86 | } |
@@ -1,211 +1,230 | |||||
1 | package org.implab.gradle.mercurial; |
|
1 | package org.implab.gradle.mercurial; | |
2 |
|
2 | |||
3 | import java.io.Serializable; |
|
3 | import java.io.Serializable; | |
4 | import java.util.Objects; |
|
4 | import java.util.Objects; | |
5 | import java.util.Optional; |
|
5 | import java.util.Optional; | |
6 | import java.util.regex.Matcher; |
|
6 | import java.util.regex.Matcher; | |
7 | import java.util.regex.Pattern; |
|
7 | import java.util.regex.Pattern; | |
8 |
|
8 | |||
9 | import javax.annotation.Nonnull; |
|
9 | import javax.annotation.Nonnull; | |
10 |
|
10 | |||
|
11 | /** | |||
|
12 | * Semantic version object. | |||
|
13 | * | |||
|
14 | * <p> | |||
|
15 | * This is a readonly version record which follows general rules of | |||
|
16 | * semantic versioning. The object is serializable and can be used as | |||
|
17 | * input property value for build tasks. | |||
|
18 | */ | |||
11 | public class SemVersion implements Serializable, Comparable<SemVersion> { |
|
19 | public class SemVersion implements Serializable, Comparable<SemVersion> { | |
12 |
|
20 | |||
13 | private static final long serialVersionUID = 1L; |
|
21 | private static final long serialVersionUID = 1L; | |
14 |
|
22 | |||
15 | private static Pattern semVerPattern = Pattern.compile( |
|
23 | private static Pattern semVerPattern = Pattern.compile( | |
16 | "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"); |
|
24 | "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"); | |
17 |
|
25 | |||
18 | private static Pattern semVerLaxPattern = Pattern.compile( |
|
26 | private static Pattern semVerLaxPattern = Pattern.compile( | |
19 | "^(0|[1-9]\\d*)(?:\\.(0|[1-9]\\d*)(?:\\.(0|[1-9]\\d*))?)?(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"); |
|
27 | "^(0|[1-9]\\d*)(?:\\.(0|[1-9]\\d*)(?:\\.(0|[1-9]\\d*))?)?(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"); | |
20 |
|
28 | |||
21 | private int major; |
|
29 | private final int major; | |
22 |
|
30 | |||
23 | private int minor; |
|
31 | private final int minor; | |
24 |
|
32 | |||
25 | private int patch; |
|
33 | private final int patch; | |
26 |
|
34 | |||
27 |
private String |
|
35 | private final String preRelease; | |
|
36 | ||||
|
37 | private final String meta; | |||
28 |
|
38 | |||
29 | private String meta; |
|
39 | /** Creates the new and empty version */ | |
30 |
|
||||
31 | public SemVersion() { |
|
40 | public SemVersion() { | |
|
41 | this(0, 0, 0, null, null); | |||
32 | } |
|
42 | } | |
33 |
|
43 | |||
34 | public SemVersion(int major, int minor, int patch, String suffix, String meta) { |
|
44 | /** Creates the version object with the specified values */ | |
|
45 | public SemVersion(int major, int minor, int patch, String preRelease, String meta) { | |||
35 | this.major = major; |
|
46 | this.major = major; | |
36 | this.minor = minor; |
|
47 | this.minor = minor; | |
37 | this.patch = patch; |
|
48 | this.patch = patch; | |
38 | this.suffix = suffix; |
|
49 | this.preRelease = preRelease; | |
39 | this.meta = meta; |
|
50 | this.meta = meta; | |
40 | } |
|
51 | } | |
41 |
|
52 | |||
|
53 | /** Creates the version object with the specified values */ | |||
42 | public SemVersion(int major, int minor, int patch) { |
|
54 | public SemVersion(int major, int minor, int patch) { | |
43 | this(major, minor, patch, null, null); |
|
55 | this(major, minor, patch, null, null); | |
44 | } |
|
56 | } | |
45 |
|
57 | |||
46 | public SemVersion(SemVersion src) { |
|
58 | /** Returns the major part of the version */ | |
47 | this(src.major, src.minor, src.patch, src.suffix, src.meta); |
|
|||
48 | } |
|
|||
49 |
|
||||
50 | public int getMajor() { |
|
59 | public int getMajor() { | |
51 | return major; |
|
60 | return major; | |
52 | } |
|
61 | } | |
53 |
|
62 | |||
54 | public void setMajor(int major) { |
|
63 | /** Returns the minor part of the version */ | |
55 | this.major = major; |
|
|||
56 | } |
|
|||
57 |
|
||||
58 | public int getMinor() { |
|
64 | public int getMinor() { | |
59 | return minor; |
|
65 | return minor; | |
60 | } |
|
66 | } | |
61 |
|
67 | |||
62 | public void setMinor(int minor) { |
|
68 | /** Returns the patch part of the version */ | |
63 | this.minor = minor; |
|
|||
64 | } |
|
|||
65 |
|
||||
66 | public int getPatch() { |
|
69 | public int getPatch() { | |
67 | return patch; |
|
70 | return patch; | |
68 | } |
|
71 | } | |
69 |
|
72 | |||
70 | public void setPatch(int patch) { |
|
73 | /** Gets the optional pre-release version part */ | |
71 | this.patch = patch; |
|
74 | public Optional<String> getPreRelease() { | |
72 | } |
|
75 | return Optional.ofNullable(preRelease); | |
73 |
|
||||
74 | public Optional<String> getSuffix() { |
|
|||
75 | return Optional.ofNullable(suffix); |
|
|||
76 | } |
|
|||
77 |
|
||||
78 | public void setSuffix(String suffix) { |
|
|||
79 | this.suffix = suffix; |
|
|||
80 | } |
|
76 | } | |
81 |
|
77 | |||
82 | public Optional<String> getMeta() { |
|
78 | public Optional<String> getMeta() { | |
83 | return Optional.ofNullable(meta); |
|
79 | return Optional.ofNullable(meta); | |
84 | } |
|
80 | } | |
85 |
|
81 | |||
86 | public void setMeta(String meta) { |
|
|||
87 | this.meta = meta; |
|
|||
88 | } |
|
|||
89 |
|
||||
90 | public boolean isRelease() { |
|
82 | public boolean isRelease() { | |
91 |
return get |
|
83 | return getPreRelease().isEmpty(); | |
92 | } |
|
84 | } | |
93 |
|
85 | |||
94 | @Override |
|
86 | @Override | |
95 | public String toString() { |
|
87 | public String toString() { | |
96 | StringBuilder sb = new StringBuilder(); |
|
88 | StringBuilder sb = new StringBuilder(); | |
97 |
|
89 | |||
98 | sb.append(major).append(".").append(minor).append(".").append(patch); |
|
90 | sb.append(major).append(".").append(minor).append(".").append(patch); | |
99 |
get |
|
91 | getPreRelease().ifPresent(s -> sb.append("-").append(s)); | |
100 | getMeta().ifPresent(m -> sb.append("+").append(m)); |
|
92 | getMeta().ifPresent(m -> sb.append("+").append(m)); | |
101 |
|
93 | |||
102 | return sb.toString(); |
|
94 | return sb.toString(); | |
103 | } |
|
95 | } | |
104 |
|
96 | |||
105 | @Override |
|
97 | @Override | |
106 | public int compareTo(SemVersion other) { |
|
98 | public int compareTo(SemVersion other) { | |
107 | int res = Integer.compare(major, other.major); |
|
99 | int res = Integer.compare(major, other.major); | |
108 | if (res != 0) |
|
100 | if (res != 0) | |
109 | return res; |
|
101 | return res; | |
110 | res = Integer.compare(minor, other.minor); |
|
102 | res = Integer.compare(minor, other.minor); | |
111 | if (res != 0) |
|
103 | if (res != 0) | |
112 | return res; |
|
104 | return res; | |
113 | res = Integer.compare(patch, other.patch); |
|
105 | res = Integer.compare(patch, other.patch); | |
114 |
|
106 | |||
115 |
return get |
|
107 | return getPreRelease() | |
116 |
// if we have suffix, chec |
|
108 | // if we have suffix, check the other version suffix, | |
117 | // then another version is bigger: 1.0.0-rc < 1.0.0 |
|
109 | // if the other has no suffix then it's greater. | |
118 | .map(s1 -> other.getSuffix().map(s2 -> s1.compareTo(s2)).orElse(-1)) |
|
110 | // 1.0.0-rc < 1.0.0 | |
|
111 | .map(s1 -> other.getPreRelease().map(s2 -> s1.compareTo(s2)).orElse(-1)) | |||
119 | // if we don't have the suffix |
|
112 | // if we don't have the suffix | |
120 |
.orElse(other.get |
|
113 | .orElse(other.getPreRelease().isPresent() ? 1 : 0); | |
121 |
|
114 | |||
122 | } |
|
115 | } | |
123 |
|
116 | |||
124 | public SemVersion release() { |
|
117 | /** Removes the tag (pre-release and meta information) */ | |
|
118 | public SemVersion withNoSuffix() { | |||
125 | return new SemVersion(major, minor, patch, null, null); |
|
119 | return new SemVersion(major, minor, patch, null, null); | |
126 | } |
|
120 | } | |
127 |
|
121 | |||
128 | public SemVersion suffix(String suffix) { |
|
122 | /** Sets the specified suffix leaving other parts unchanged */ | |
129 | return new SemVersion(major, minor, patch, suffix, meta); |
|
123 | public SemVersion withPreRelease(String preRelease) { | |
|
124 | return new SemVersion(major, minor, patch, preRelease, meta); | |||
130 | } |
|
125 | } | |
131 |
|
126 | |||
132 | public SemVersion suffix() { |
|
127 | /** Removes pre-release information leaving other parts unchanged */ | |
|
128 | public SemVersion withNoPreRelease() { | |||
133 | return new SemVersion(major, minor, patch, null, meta); |
|
129 | return new SemVersion(major, minor, patch, null, meta); | |
134 | } |
|
130 | } | |
135 |
|
131 | |||
136 | public SemVersion meta(String meta) { |
|
132 | /** Sets the specified build metadata */ | |
137 | return new SemVersion(major, minor, patch, suffix, meta); |
|
133 | public SemVersion withMeta(String meta) { | |
|
134 | return new SemVersion(major, minor, patch, preRelease, meta); | |||
138 | } |
|
135 | } | |
139 |
|
136 | |||
140 | public SemVersion meta() { |
|
137 | /** Removes the build metadata from the version */ | |
141 | return new SemVersion(major, minor, patch, suffix, null); |
|
138 | public SemVersion withNoMeta() { | |
|
139 | return new SemVersion(major, minor, patch, preRelease, null); | |||
142 | } |
|
140 | } | |
143 |
|
141 | |||
144 | public SemVersion patch(int patch) { |
|
142 | /** Sets the specified patch version */ | |
145 | return new SemVersion(major, minor, patch, suffix, meta); |
|
143 | public SemVersion withPatch(int patch) { | |
|
144 | return new SemVersion(major, minor, patch, preRelease, meta); | |||
146 | } |
|
145 | } | |
147 |
|
146 | |||
148 | public SemVersion minor(int minor) { |
|
147 | /** Sets the specified minor version */ | |
149 | return new SemVersion(major, minor, patch, suffix, meta); |
|
148 | public SemVersion withMinor(int minor) { | |
|
149 | return new SemVersion(major, minor, patch, preRelease, meta); | |||
150 | } |
|
150 | } | |
151 |
|
151 | |||
152 | public SemVersion major(int major) { |
|
152 | /** Sets the specified major version */ | |
153 | return new SemVersion(major, minor, patch, suffix, meta); |
|
153 | public SemVersion withMajor(int major) { | |
|
154 | return new SemVersion(major, minor, patch, preRelease, meta); | |||
154 | } |
|
155 | } | |
155 |
|
156 | |||
|
157 | /** Adds the specified number to the patch version */ | |||
156 | public SemVersion addPatch(int number) { |
|
158 | public SemVersion addPatch(int number) { | |
157 |
return new SemVersion(major, minor, patch + number, |
|
159 | return new SemVersion(major, minor, patch + number, preRelease, meta); | |
158 | } |
|
160 | } | |
159 |
|
161 | |||
|
162 | /** Adds the specified number to the minor version */ | |||
160 | public SemVersion addMinor(int number) { |
|
163 | public SemVersion addMinor(int number) { | |
161 |
return new SemVersion(major, minor + number, patch, |
|
164 | return new SemVersion(major, minor + number, patch, preRelease, meta); | |
162 | } |
|
165 | } | |
163 |
|
166 | |||
|
167 | /** Adds the specified number to the major version */ | |||
164 | public SemVersion addMajor(int number) { |
|
168 | public SemVersion addMajor(int number) { | |
165 |
return new SemVersion(major + number, minor, patch, |
|
169 | return new SemVersion(major + number, minor, patch, preRelease, meta); | |
166 | } |
|
170 | } | |
167 |
|
171 | |||
|
172 | /** Generated the next minor version by incrementing the minor version, | |||
|
173 | * setting the patch version to 0 and removing the pre-release information. | |||
|
174 | * The build metadata is left unchanged. | |||
|
175 | * | |||
|
176 | * <p>Use this method to publish next minor version. | |||
|
177 | */ | |||
168 | public SemVersion nextMinor() { |
|
178 | public SemVersion nextMinor() { | |
169 | return new SemVersion(major, minor + 1, 0, null, meta); |
|
179 | return new SemVersion(major, minor + 1, 0, null, meta); | |
170 | } |
|
180 | } | |
171 |
|
181 | |||
|
182 | /** Generated the next minor version by incrementing the major version, | |||
|
183 | * setting the minor version and the patch to 0 and removing the | |||
|
184 | * pre-release information. The build metadata is left unchanged. | |||
|
185 | * | |||
|
186 | * <p>Use this method to publish next major version. | |||
|
187 | */ | |||
172 | public SemVersion nextMajor() { |
|
188 | public SemVersion nextMajor() { | |
173 | return new SemVersion(major + 1, 0, 0, null, meta); |
|
189 | return new SemVersion(major + 1, 0, 0, null, meta); | |
174 | } |
|
190 | } | |
175 |
|
191 | |||
|
192 | /** Parses the version string. */ | |||
176 | public static Optional<SemVersion> tryParse(@Nonnull String str) { |
|
193 | public static Optional<SemVersion> tryParse(@Nonnull String str) { | |
177 | Objects.requireNonNull(str); |
|
194 | Objects.requireNonNull(str); | |
178 |
|
195 | |||
179 | Matcher match = semVerPattern.matcher(str); |
|
196 | Matcher match = semVerPattern.matcher(str); | |
180 |
|
197 | |||
181 | return match.matches() ? Optional.of(new SemVersion(Integer.parseInt(match.group(1)), |
|
198 | return match.matches() ? Optional.of(new SemVersion(Integer.parseInt(match.group(1)), | |
182 | Integer.parseInt(match.group(2)), Integer.parseInt(match.group(3)), match.group(4), match.group(5))) |
|
199 | Integer.parseInt(match.group(2)), Integer.parseInt(match.group(3)), match.group(4), match.group(5))) | |
183 | : Optional.empty(); |
|
200 | : Optional.empty(); | |
184 | } |
|
201 | } | |
185 |
|
202 | |||
|
203 | /** Parses the version string. When */ | |||
186 | public static Optional<SemVersion> tryParseLax(@Nonnull String str) { |
|
204 | public static Optional<SemVersion> tryParseLax(@Nonnull String str) { | |
187 | Objects.requireNonNull(str); |
|
205 | Objects.requireNonNull(str); | |
188 |
|
206 | |||
189 | Matcher match = semVerLaxPattern.matcher(str); |
|
207 | Matcher match = semVerLaxPattern.matcher(str); | |
190 |
|
208 | |||
191 | return match.matches() ? Optional.of(new SemVersion(Integer.parseInt(match.group(1)), |
|
209 | return match.matches() ? Optional.of(new SemVersion(Integer.parseInt(match.group(1)), | |
192 | Integer.parseInt(Optional.ofNullable(match.group(2)).orElse("0")), |
|
210 | Integer.parseInt(Optional.ofNullable(match.group(2)).orElse("0")), | |
193 | Integer.parseInt(Optional.ofNullable(match.group(3)).orElse("0")), match.group(4), match.group(5))) |
|
211 | Integer.parseInt(Optional.ofNullable(match.group(3)).orElse("0")), match.group(4), match.group(5))) | |
194 | : Optional.empty(); |
|
212 | : Optional.empty(); | |
195 | } |
|
213 | } | |
196 |
|
214 | |||
197 | public static SemVersion toSemVersion(Object value, boolean strict) { |
|
215 | public static SemVersion toSemVersion(Object value, boolean strict) { | |
198 | if (value == null) { |
|
216 | if (value == null) { | |
199 | return new SemVersion(); |
|
217 | return new SemVersion(); | |
200 | } else if (value instanceof SemVersion) { |
|
218 | } else if (value instanceof SemVersion) { | |
201 |
return |
|
219 | return (SemVersion) value; | |
202 | } else { |
|
220 | } else { | |
203 | Optional<SemVersion> semver = strict ? tryParse(value.toString()) : tryParseLax(value.toString()); |
|
221 | Optional<SemVersion> semver = strict ? tryParse(value.toString()) : tryParseLax(value.toString()); | |
204 |
return semver.orElseThrow(() -> new IllegalArgumentException( |
|
222 | return semver.orElseThrow(() -> new IllegalArgumentException( | |
|
223 | String.format("Failed to parse semver '%s', strict=%s", value, strict))); | |||
205 | } |
|
224 | } | |
206 | } |
|
225 | } | |
207 |
|
226 | |||
208 | public static SemVersion toSemVersion(Object value) { |
|
227 | public static SemVersion toSemVersion(Object value) { | |
209 | return toSemVersion(value, false); |
|
228 | return toSemVersion(value, false); | |
210 | } |
|
229 | } | |
211 | } |
|
230 | } |
@@ -1,84 +1,84 | |||||
1 | package org.implab.gradle.mercurial.tasks; |
|
1 | package org.implab.gradle.mercurial.tasks; | |
2 |
|
2 | |||
3 | import java.io.IOException; |
|
3 | import java.io.IOException; | |
4 | import java.util.ArrayList; |
|
4 | import java.util.ArrayList; | |
5 | import java.util.List; |
|
5 | import java.util.List; | |
6 |
|
6 | |||
7 | import javax.inject.Inject; |
|
7 | import javax.inject.Inject; | |
8 |
|
8 | |||
9 | import org.gradle.api.DefaultTask; |
|
9 | import org.gradle.api.DefaultTask; | |
10 | import org.gradle.api.model.ObjectFactory; |
|
10 | import org.gradle.api.model.ObjectFactory; | |
11 | import org.gradle.api.provider.ListProperty; |
|
11 | import org.gradle.api.provider.ListProperty; | |
12 | import org.gradle.api.provider.Property; |
|
12 | import org.gradle.api.provider.Property; | |
|
13 | import org.gradle.api.tasks.Internal; | |||
13 | import org.gradle.api.tasks.TaskAction; |
|
14 | import org.gradle.api.tasks.TaskAction; | |
14 | import org.implab.gradle.Utils; |
|
15 | import org.implab.gradle.Utils; | |
15 | import org.implab.gradle.mercurial.MercurialExtension; |
|
16 | import org.implab.gradle.mercurial.MercurialExtension; | |
16 |
|
17 | |||
17 | import groovy.transform.Internal; |
|
|||
18 |
|
||||
19 | public class HgBookmark extends DefaultTask { |
|
18 | public class HgBookmark extends DefaultTask { | |
20 |
|
19 | |||
21 | private final Property<String> cliCmd; |
|
20 | private final Property<String> cliCmd; | |
22 |
|
21 | |||
23 | private final Property<Boolean> inactive; |
|
22 | private final Property<Boolean> inactive; | |
24 |
|
23 | |||
25 | private final Property<Boolean> force; |
|
24 | private final Property<Boolean> force; | |
26 |
|
25 | |||
27 | private final ListProperty<String> bookmarks; |
|
26 | private final ListProperty<String> bookmarks; | |
28 |
|
27 | |||
29 | private String commandOutput; |
|
28 | private String commandOutput; | |
30 |
|
29 | |||
|
30 | @Internal | |||
31 | protected MercurialExtension getMercurialExtension() { |
|
31 | protected MercurialExtension getMercurialExtension() { | |
32 | return getProject().getExtensions().getByType(MercurialExtension.class); |
|
32 | return getProject().getExtensions().getByType(MercurialExtension.class); | |
33 | } |
|
33 | } | |
34 |
|
34 | |||
35 | @Inject |
|
35 | @Inject | |
36 | public HgBookmark(ObjectFactory factory) { |
|
36 | public HgBookmark(ObjectFactory factory) { | |
37 | cliCmd = factory.property(String.class); |
|
37 | cliCmd = factory.property(String.class); | |
38 | inactive = factory.property(Boolean.class); |
|
38 | inactive = factory.property(Boolean.class); | |
39 | force = factory.property(Boolean.class); |
|
39 | force = factory.property(Boolean.class); | |
40 | bookmarks = factory.listProperty(String.class); |
|
40 | bookmarks = factory.listProperty(String.class); | |
41 | cliCmd.convention(getMercurialExtension().getHgCmd()); |
|
41 | cliCmd.convention(getMercurialExtension().getHgCmd()); | |
42 |
|
42 | |||
43 | onlyIf(t -> !getBookmarks().get().isEmpty()); |
|
43 | onlyIf(t -> !getBookmarks().get().isEmpty()); | |
44 | } |
|
44 | } | |
45 |
|
45 | |||
46 | @Internal |
|
46 | @Internal | |
47 | public Property<Boolean> getInactive() { |
|
47 | public Property<Boolean> getInactive() { | |
48 | return inactive; |
|
48 | return inactive; | |
49 | } |
|
49 | } | |
50 |
|
50 | |||
51 | @Internal |
|
51 | @Internal | |
52 | public Property<Boolean> getForce() { |
|
52 | public Property<Boolean> getForce() { | |
53 | return force; |
|
53 | return force; | |
54 | } |
|
54 | } | |
55 |
|
55 | |||
56 | @Internal |
|
56 | @Internal | |
57 | public String getCommandOutput() { |
|
57 | public String getCommandOutput() { | |
58 | return commandOutput; |
|
58 | return commandOutput; | |
59 | } |
|
59 | } | |
60 |
|
60 | |||
61 | @Internal |
|
61 | @Internal | |
62 | public ListProperty<String> getBookmarks() { |
|
62 | public ListProperty<String> getBookmarks() { | |
63 | return bookmarks; |
|
63 | return bookmarks; | |
64 | } |
|
64 | } | |
65 |
|
65 | |||
66 | @TaskAction |
|
66 | @TaskAction | |
67 | public void Run() throws IOException, InterruptedException, Exception { |
|
67 | public void Run() throws IOException, InterruptedException, Exception { | |
68 | List<String> commandLine = new ArrayList<>(); |
|
68 | List<String> commandLine = new ArrayList<>(); | |
69 |
|
69 | |||
70 | commandLine.add(cliCmd.get()); |
|
70 | commandLine.add(cliCmd.get()); | |
71 | commandLine.add("bookmark"); |
|
71 | commandLine.add("bookmark"); | |
72 | if(inactive.isPresent()) |
|
72 | if(inactive.isPresent()) | |
73 | commandLine.add("-i"); |
|
73 | commandLine.add("-i"); | |
74 | if(force.isPresent()) |
|
74 | if(force.isPresent()) | |
75 | commandLine.add("-f"); |
|
75 | commandLine.add("-f"); | |
76 |
|
76 | |||
77 | commandLine.addAll(bookmarks.get()); |
|
77 | commandLine.addAll(bookmarks.get()); | |
78 |
|
78 | |||
79 | getLogger().info("Starting: {}", commandLine); |
|
79 | getLogger().info("Starting: {}", commandLine); | |
80 |
|
80 | |||
81 | commandOutput = Utils.execCmd(commandLine, getMercurialExtension().getOutputCharset().name()); |
|
81 | commandOutput = Utils.execCmd(commandLine, getMercurialExtension().getOutputCharset().name()); | |
82 | } |
|
82 | } | |
83 |
|
83 | |||
84 | } |
|
84 | } |
@@ -1,79 +1,76 | |||||
1 | package org.implab.gradle.mercurial.tasks; |
|
1 | package org.implab.gradle.mercurial.tasks; | |
2 |
|
2 | |||
3 | import java.io.IOException; |
|
3 | import java.io.IOException; | |
4 | import java.util.ArrayList; |
|
4 | import java.util.ArrayList; | |
5 | import java.util.List; |
|
5 | import java.util.List; | |
6 |
|
6 | |||
7 | import javax.inject.Inject; |
|
7 | import javax.inject.Inject; | |
8 |
|
8 | |||
9 | import org.gradle.api.DefaultTask; |
|
9 | import org.gradle.api.DefaultTask; | |
10 | import org.gradle.api.model.ObjectFactory; |
|
10 | import org.gradle.api.model.ObjectFactory; | |
11 | import org.gradle.api.provider.ListProperty; |
|
11 | import org.gradle.api.provider.ListProperty; | |
12 | import org.gradle.api.provider.Property; |
|
12 | import org.gradle.api.provider.Property; | |
13 |
import org.gradle.api.tasks.In |
|
13 | import org.gradle.api.tasks.Internal; | |
14 | import org.gradle.api.tasks.SkipWhenEmpty; |
|
|||
15 | import org.gradle.api.tasks.TaskAction; |
|
14 | import org.gradle.api.tasks.TaskAction; | |
16 | import org.implab.gradle.Utils; |
|
15 | import org.implab.gradle.Utils; | |
17 | import org.implab.gradle.mercurial.MercurialExtension; |
|
16 | import org.implab.gradle.mercurial.MercurialExtension; | |
18 |
|
17 | |||
19 | import groovy.transform.Internal; |
|
|||
20 |
|
||||
21 | public class HgTag extends DefaultTask { |
|
18 | public class HgTag extends DefaultTask { | |
22 |
|
19 | |||
23 | private final Property<String> cliCmd; |
|
20 | private final Property<String> cliCmd; | |
24 |
|
21 | |||
25 | private final Property<Boolean> force; |
|
22 | private final Property<Boolean> force; | |
26 |
|
23 | |||
27 | private final ListProperty<String> tags; |
|
24 | private final ListProperty<String> tags; | |
28 |
|
25 | |||
29 | private String commandOutput; |
|
26 | private String commandOutput; | |
30 |
|
27 | |||
|
28 | @Internal | |||
31 | protected MercurialExtension getMercurialExtension() { |
|
29 | protected MercurialExtension getMercurialExtension() { | |
32 | return getProject().getExtensions().getByType(MercurialExtension.class); |
|
30 | return getProject().getExtensions().getByType(MercurialExtension.class); | |
33 | } |
|
31 | } | |
34 |
|
32 | |||
35 | @Inject |
|
33 | @Inject | |
36 | public HgTag(ObjectFactory factory) { |
|
34 | public HgTag(ObjectFactory factory) { | |
37 | cliCmd = factory.property(String.class); |
|
35 | cliCmd = factory.property(String.class); | |
38 | force = factory.property(Boolean.class); |
|
36 | force = factory.property(Boolean.class); | |
39 | tags = factory.listProperty(String.class); |
|
37 | tags = factory.listProperty(String.class); | |
40 | cliCmd.convention(getMercurialExtension().getHgCmd()); |
|
38 | cliCmd.convention(getMercurialExtension().getHgCmd()); | |
41 |
|
39 | |||
42 | onlyIf(t -> !getTags().get().isEmpty()); |
|
40 | onlyIf(t -> !getTags().get().isEmpty()); | |
43 | } |
|
41 | } | |
44 |
|
42 | |||
45 | @Internal |
|
43 | @Internal | |
46 | public Property<Boolean> getForce() { |
|
44 | public Property<Boolean> getForce() { | |
47 | return force; |
|
45 | return force; | |
48 | } |
|
46 | } | |
49 |
|
47 | |||
50 | @Internal |
|
48 | @Internal | |
51 | public String getCommandOutput() { |
|
49 | public String getCommandOutput() { | |
52 | return commandOutput; |
|
50 | return commandOutput; | |
53 | } |
|
51 | } | |
54 |
|
52 | |||
55 |
@In |
|
53 | @Internal | |
56 | @SkipWhenEmpty |
|
|||
57 | public ListProperty<String> getTags() { |
|
54 | public ListProperty<String> getTags() { | |
58 | return tags; |
|
55 | return tags; | |
59 | } |
|
56 | } | |
60 |
|
57 | |||
61 | @TaskAction |
|
58 | @TaskAction | |
62 | public void Run() throws IOException, InterruptedException, Exception { |
|
59 | public void Run() throws IOException, InterruptedException, Exception { | |
63 | List<String> commandLine = new ArrayList<>(); |
|
60 | List<String> commandLine = new ArrayList<>(); | |
64 |
|
61 | |||
65 | commandLine.add(cliCmd.get()); |
|
62 | commandLine.add(cliCmd.get()); | |
66 |
|
63 | |||
67 | commandLine.add("tag"); |
|
64 | commandLine.add("tag"); | |
68 |
|
65 | |||
69 | if(force.isPresent()) |
|
66 | if(force.isPresent()) | |
70 | commandLine.add("-f"); |
|
67 | commandLine.add("-f"); | |
71 |
|
68 | |||
72 | commandLine.addAll(tags.get()); |
|
69 | commandLine.addAll(tags.get()); | |
73 |
|
70 | |||
74 | getLogger().info("Starting: {}", commandLine); |
|
71 | getLogger().info("Starting: {}", commandLine); | |
75 |
|
72 | |||
76 | commandOutput = Utils.execCmd(commandLine, getMercurialExtension().getOutputCharset().name()); |
|
73 | commandOutput = Utils.execCmd(commandLine, getMercurialExtension().getOutputCharset().name()); | |
77 | } |
|
74 | } | |
78 |
|
75 | |||
79 | } |
|
76 | } |
@@ -1,67 +1,70 | |||||
1 | package org.implab.gradle.mercurial.tasks; |
|
1 | package org.implab.gradle.mercurial.tasks; | |
2 |
|
2 | |||
3 | import java.io.IOException; |
|
3 | import java.io.IOException; | |
4 | import java.util.ArrayList; |
|
4 | import java.util.ArrayList; | |
5 | import java.util.List; |
|
5 | import java.util.List; | |
6 |
|
6 | |||
7 | import org.gradle.api.DefaultTask; |
|
7 | import org.gradle.api.DefaultTask; | |
8 | import org.gradle.api.provider.Property; |
|
8 | import org.gradle.api.provider.Property; | |
9 | import org.gradle.api.provider.Provider; |
|
9 | import org.gradle.api.provider.Provider; | |
|
10 | import org.gradle.api.tasks.Internal; | |||
10 | import org.gradle.api.tasks.TaskAction; |
|
11 | import org.gradle.api.tasks.TaskAction; | |
11 | import org.implab.gradle.Utils; |
|
12 | import org.implab.gradle.Utils; | |
12 | import org.implab.gradle.mercurial.MercurialExtension; |
|
13 | import org.implab.gradle.mercurial.MercurialExtension; | |
13 |
|
14 | |||
14 | public class HgTask extends DefaultTask { |
|
15 | public class HgTask extends DefaultTask { | |
15 |
|
16 | |||
16 | private final Property<String> cliCmd; |
|
17 | private final Property<String> cliCmd; | |
17 |
|
18 | |||
18 | private List<Provider<String>> commandArgs; |
|
19 | private List<Provider<String>> commandArgs; | |
19 |
|
20 | |||
20 | private String commandOutput; |
|
21 | private String commandOutput; | |
21 |
|
22 | |||
|
23 | @Internal | |||
22 | protected MercurialExtension getMercurialExtension() { |
|
24 | protected MercurialExtension getMercurialExtension() { | |
23 | return getProject().getExtensions().getByType(MercurialExtension.class); |
|
25 | return getProject().getExtensions().getByType(MercurialExtension.class); | |
24 | } |
|
26 | } | |
25 |
|
27 | |||
26 | public HgTask() { |
|
28 | public HgTask() { | |
27 | cliCmd = getProject().getObjects().property(String.class); |
|
29 | cliCmd = getProject().getObjects().property(String.class); | |
28 | cliCmd.convention(getMercurialExtension().getHgCmd()); |
|
30 | cliCmd.convention(getMercurialExtension().getHgCmd()); | |
29 |
|
31 | |||
30 | } |
|
32 | } | |
31 |
|
33 | |||
|
34 | @Internal | |||
32 | public String getCommandOutput() { |
|
35 | public String getCommandOutput() { | |
33 | return commandOutput; |
|
36 | return commandOutput; | |
34 | } |
|
37 | } | |
35 |
|
38 | |||
36 | public void clearCommandArgs() { |
|
39 | public void clearCommandArgs() { | |
37 | commandArgs.clear(); |
|
40 | commandArgs.clear(); | |
38 | } |
|
41 | } | |
39 |
|
42 | |||
40 | public void commandArgs(Object... args) { |
|
43 | public void commandArgs(Object... args) { | |
41 | for (Object arg : args) { |
|
44 | for (Object arg : args) { | |
42 | if (arg == null) |
|
45 | if (arg == null) | |
43 | continue; |
|
46 | continue; | |
44 | if (arg instanceof Provider<?>) |
|
47 | if (arg instanceof Provider<?>) | |
45 | commandArgs.add(((Provider<?>) arg).map(x -> x.toString())); |
|
48 | commandArgs.add(((Provider<?>) arg).map(x -> x.toString())); | |
46 | else |
|
49 | else | |
47 | commandArgs.add(getProject().getProviders().provider(() -> arg.toString())); |
|
50 | commandArgs.add(getProject().getProviders().provider(() -> arg.toString())); | |
48 | } |
|
51 | } | |
49 | } |
|
52 | } | |
50 |
|
53 | |||
51 | @TaskAction |
|
54 | @TaskAction | |
52 | public void Run() throws IOException, InterruptedException, Exception { |
|
55 | public void Run() throws IOException, InterruptedException, Exception { | |
53 | List<String> commandLine = new ArrayList<>(); |
|
56 | List<String> commandLine = new ArrayList<>(); | |
54 |
|
57 | |||
55 | commandLine.add(cliCmd.get()); |
|
58 | commandLine.add(cliCmd.get()); | |
56 |
|
59 | |||
57 | for (Provider<String> arg : commandArgs) { |
|
60 | for (Provider<String> arg : commandArgs) { | |
58 | if (arg.isPresent()) |
|
61 | if (arg.isPresent()) | |
59 | commandLine.add(arg.get()); |
|
62 | commandLine.add(arg.get()); | |
60 | } |
|
63 | } | |
61 |
|
64 | |||
62 | getLogger().info("Starting: ", commandLine); |
|
65 | getLogger().info("Starting: ", commandLine); | |
63 |
|
66 | |||
64 | commandOutput = Utils.execCmd(commandLine, getMercurialExtension().getOutputCharset().name()); |
|
67 | commandOutput = Utils.execCmd(commandLine, getMercurialExtension().getOutputCharset().name()); | |
65 | } |
|
68 | } | |
66 |
|
69 | |||
67 | } |
|
70 | } |
General Comments 0
You need to be logged in to leave comments.
Login now