Skip to content

Commit d9038ba

Browse files
tulinkryVladimir Kotal
authored andcommitted
check git version in GitRepository#isWorking() (#2681)
fixes #2664
1 parent e6cb439 commit d9038ba

File tree

4 files changed

+242
-8
lines changed

4 files changed

+242
-8
lines changed

dev/before

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ echo "Environment variables:"
44
env | sort
55

66
echo "SCM versions:"
7-
if `which bk`; then bk --version; fi
8-
if `which hg`; then hg --version; fi
9-
if `which git`; then git --version; fi
10-
if `which svn`; then svn --version; fi
11-
if `which cvs`; then cvs --version; fi
12-
if `which mtn`; then mtn --version; fi
13-
if `which bzr`; then bzr version; fi
7+
if command -v bk; then bk --version; fi
8+
if command -v hg; then hg --version; fi
9+
if command -v git; then git --version; fi
10+
if command -v svn; then svn --version; fi
11+
if command -v cvs; then cvs --version; fi
12+
if command -v mtn; then mtn --version; fi
13+
if command -v bzr; then bzr version; fi

opengrok-indexer/src/main/java/org/opengrok/indexer/history/GitRepository.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.opengrok.indexer.util.BufferSink;
4848
import org.opengrok.indexer.util.Executor;
4949
import org.opengrok.indexer.util.StringUtils;
50+
import org.opengrok.indexer.util.Version;
5051

5152
/**
5253
* Access to a Git repository.
@@ -85,6 +86,13 @@ public class GitRepository extends Repository {
8586
*/
8687
private static final String GIT_DATE_OPT = "--date=iso8601-strict";
8788

89+
/**
90+
* Minimum git version which supports the date format
91+
*
92+
* @see #GIT_DATE_OPT
93+
*/
94+
private static final Version MINIMUM_VERSION = new Version(2, 1, 2);
95+
8896
public GitRepository() {
8997
type = "git";
9098
/*
@@ -521,8 +529,22 @@ boolean supportsSubRepositories() {
521529
public boolean isWorking() {
522530
if (working == null) {
523531
ensureCommand(CMD_PROPERTY_KEY, CMD_FALLBACK);
524-
working = checkCmd(RepoCommand, "--help");
532+
Executor exec = new Executor(new String[]{RepoCommand, "--version"});
533+
534+
if (exec.exec(false) == 0) {
535+
final String outputVersion = exec.getOutputString();
536+
final String version = outputVersion.replaceAll(".*? version (\\d+(\\.\\d+)*).*", "$1");
537+
try {
538+
working = Version.from(version).compareTo(MINIMUM_VERSION) >= 0;
539+
} catch (NumberFormatException ex) {
540+
LOGGER.log(Level.WARNING, String.format("Unable to detect git version from %s", outputVersion), ex);
541+
working = false;
542+
}
543+
} else {
544+
working = false;
545+
}
525546
}
547+
526548
return working;
527549
}
528550

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
* CDDL HEADER START
3+
*
4+
* The contents of this file are subject to the terms of the
5+
* Common Development and Distribution License (the "License").
6+
* You may not use this file except in compliance with the License.
7+
*
8+
* See LICENSE.txt included in this distribution for the specific
9+
* language governing permissions and limitations under the License.
10+
*
11+
* When distributing Covered Code, include this CDDL HEADER in each
12+
* file and include the License file at LICENSE.txt.
13+
* If applicable, add the following below this CDDL HEADER, with the
14+
* fields enclosed by brackets "[]" replaced with your own identifying
15+
* information: Portions Copyright [yyyy] [name of copyright owner]
16+
*
17+
* CDDL HEADER END
18+
*/
19+
20+
/*
21+
* Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
22+
* Portions Copyright (c) 2019, Krystof Tulinger (tulinkry).
23+
*/
24+
package org.opengrok.indexer.util;
25+
26+
import java.util.Arrays;
27+
import java.util.stream.Stream;
28+
29+
/**
30+
* This class implements portions of semantic versioning from version noted as
31+
* <pre>
32+
* a.b.c.d.e.f
33+
* </pre>
34+
* where
35+
* <pre>
36+
* a - major
37+
* b - minor
38+
* c - patch
39+
* d ... - others
40+
* </pre>
41+
*
42+
* @author Krystof Tulinger (tulinkry)
43+
* @see <a href="https://semver.org/">https://semver.org/</a>
44+
*/
45+
public class Version implements Comparable<Version> {
46+
private final Integer[] versions;
47+
48+
/**
49+
* Construct the version from integer parts.
50+
* The order is:
51+
* <ol>
52+
* <li>major</li>
53+
* <li>minor</li>
54+
* <li>patch</li>
55+
* <li>... others</li>
56+
* </ol>
57+
*
58+
* @param parts integer values for version partials
59+
*/
60+
public Version(Integer... parts) {
61+
// cut off trailing zeros
62+
int cutOffLength = parts.length;
63+
for (int i = parts.length - 1; i >= 0; i--) {
64+
if (parts[i] != 0) {
65+
break;
66+
}
67+
cutOffLength--;
68+
}
69+
versions = Arrays.copyOf(parts, cutOffLength);
70+
}
71+
72+
/**
73+
* Construct the version from a string.
74+
*
75+
* @param string string representing the version (e. g. 1.2.1)
76+
* @return the new instance of version from the string
77+
* @throws NumberFormatException when parts can not be converted to integers
78+
*/
79+
public static Version from(String string) throws NumberFormatException {
80+
return new Version(
81+
Stream.of(string.trim().split("\\."))
82+
.map(String::trim)
83+
.map(Integer::parseInt)
84+
.toArray(Integer[]::new)
85+
);
86+
}
87+
88+
@Override
89+
public boolean equals(Object o) {
90+
if (this == o) {
91+
return true;
92+
}
93+
if (o == null || getClass() != o.getClass()) {
94+
return false;
95+
}
96+
Version version = (Version) o;
97+
return Arrays.equals(versions, version.versions);
98+
}
99+
100+
@Override
101+
public int hashCode() {
102+
return Arrays.hashCode(versions);
103+
}
104+
105+
@Override
106+
public int compareTo(Version o) {
107+
if (o == null) {
108+
return 1;
109+
}
110+
111+
// first different number determines the result
112+
for (int i = 0; i < Math.min(versions.length, o.versions.length); i++) {
113+
if (!versions[i].equals(o.versions[i])) {
114+
return Integer.compare(versions[i], o.versions[i]);
115+
}
116+
}
117+
118+
// the comparable parts are the same, the longer has some trailing non-null element which
119+
// makes it greater then the shorter
120+
// e. g. 1.0.0.0.1 vs. 1.0.0
121+
return Integer.compare(versions.length, o.versions.length);
122+
}
123+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
* CDDL HEADER START
3+
*
4+
* The contents of this file are subject to the terms of the
5+
* Common Development and Distribution License (the "License").
6+
* You may not use this file except in compliance with the License.
7+
*
8+
* See LICENSE.txt included in this distribution for the specific
9+
* language governing permissions and limitations under the License.
10+
*
11+
* When distributing Covered Code, include this CDDL HEADER in each
12+
* file and include the License file at LICENSE.txt.
13+
* If applicable, add the following below this CDDL HEADER, with the
14+
* fields enclosed by brackets "[]" replaced with your own identifying
15+
* information: Portions Copyright [yyyy] [name of copyright owner]
16+
*
17+
* CDDL HEADER END
18+
*/
19+
20+
/*
21+
* Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
22+
* Portions Copyright (c) 2019, Krystof Tulinger (tulinkry).
23+
*/
24+
package org.opengrok.indexer.util;
25+
26+
import org.junit.Assert;
27+
import org.junit.Test;
28+
29+
public class VersionTest {
30+
31+
@Test
32+
public void testFromString() {
33+
Assert.assertEquals(new Version(1, 2, 1), Version.from("1.2. 1 "));
34+
Assert.assertEquals(new Version(3, 2, 6), Version.from(" 3. 2.6"));
35+
Assert.assertEquals(new Version(100, 200, 104), Version.from("100. 200. 104"));
36+
Assert.assertEquals(new Version(1), Version.from(" 1 "));
37+
}
38+
39+
@Test(expected = NumberFormatException.class)
40+
public void testFromEmptyString() {
41+
Version.from("");
42+
}
43+
44+
45+
@Test(expected = NumberFormatException.class)
46+
public void testFromInvalidString() {
47+
Version.from("1.2.abcd.2");
48+
}
49+
50+
@Test
51+
public void testLowerComparsion() {
52+
Assert.assertTrue(new Version(1).compareTo(new Version(2)) < 0);
53+
Assert.assertTrue(new Version(1).compareTo(new Version(20)) < 0);
54+
Assert.assertTrue(new Version(1, 2).compareTo(new Version(1, 3)) < 0);
55+
Assert.assertTrue(new Version(1, 2).compareTo(new Version(2)) < 0);
56+
Assert.assertTrue(new Version(1, 2).compareTo(new Version(1, 100)) < 0);
57+
Assert.assertTrue(new Version(1, 2, 3).compareTo(new Version(1, 3)) < 0);
58+
Assert.assertTrue(new Version(1, 2, 3).compareTo(new Version(1, 2, 4)) < 0);
59+
Assert.assertTrue(new Version(2, 1, 2).compareTo(new Version(2, 11, 0)) < 0);
60+
Assert.assertTrue(new Version(2, 1, 2).compareTo(new Version(2, 20, 1)) < 0);
61+
Assert.assertTrue(new Version(1, 0, 0).compareTo(new Version(1, 0, 0, 0, 0, 1)) < 0);
62+
}
63+
64+
@Test
65+
public void testGreaterComparsion() {
66+
Assert.assertTrue(new Version(2).compareTo(new Version(1)) > 0);
67+
Assert.assertTrue(new Version(20).compareTo(new Version(1)) > 0);
68+
Assert.assertTrue(new Version(1, 3).compareTo(new Version(1, 2)) > 0);
69+
Assert.assertTrue(new Version(2).compareTo(new Version(1, 2)) > 0);
70+
Assert.assertTrue(new Version(1, 100).compareTo(new Version(1, 2)) > 0);
71+
Assert.assertTrue(new Version(1, 3).compareTo(new Version(1, 2, 3)) > 0);
72+
Assert.assertTrue(new Version(1, 2, 4).compareTo(new Version(1, 2, 3)) > 0);
73+
Assert.assertTrue(new Version(2, 11, 0).compareTo(new Version(2, 1, 2)) > 0);
74+
Assert.assertTrue(new Version(2, 20, 1).compareTo(new Version(2, 1, 2)) > 0);
75+
Assert.assertTrue(new Version(1, 0, 0, 0, 0, 1).compareTo(new Version(1, 0, 0)) > 0);
76+
}
77+
78+
@Test
79+
public void testEqualsComparsion() {
80+
Assert.assertTrue(new Version(1).compareTo(new Version(1)) == 0);
81+
Assert.assertTrue(new Version(1, 3).compareTo(new Version(1, 3)) == 0);
82+
Assert.assertTrue(new Version(1, 2).compareTo(new Version(1, 2)) == 0);
83+
Assert.assertTrue(new Version(1, 100).compareTo(new Version(1, 100)) == 0);
84+
Assert.assertTrue(new Version(1, 2, 3).compareTo(new Version(1, 2, 3)) == 0);
85+
Assert.assertTrue(new Version(1, 2, 4).compareTo(new Version(1, 2, 4)) == 0);
86+
Assert.assertTrue(new Version(1, 0, 0).compareTo(new Version(1, 0, 0)) == 0);
87+
Assert.assertTrue(new Version(1, 0, 0).compareTo(new Version(1, 0, 0, 0, 0)) == 0);
88+
}
89+
}

0 commit comments

Comments
 (0)