Time units supported: -milliseconds (1 ms, 2 milliseconds) -seconds (1 s, 1 sec, 1 second, 2 seconds) -minutes (1 m, 1 min, 1 minute, 2 minutes) -hours (1 h, 1 hr, 1 hour, 2 hours) -days (1 d, 1 day, 2 days) -weeks (1 w, 1 week, 2 weeks) -months (1 mon, 1 month, 2 months) -years (1 y, 1 year, 2 years) This functionality is implemented in Gerrit ConfigUtil class. Add it to JGit so it can eventually be remove from Gerrit. Change-Id: I2d6564ff656b6ab9424a9360624061c94fd5f413 Signed-off-by: Hugo Arès <hugo.ares@ericsson.com> Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>tags/v4.4.1.201607150455-r
@@ -48,6 +48,11 @@ | |||
package org.eclipse.jgit.lib; | |||
import static java.util.concurrent.TimeUnit.DAYS; | |||
import static java.util.concurrent.TimeUnit.HOURS; | |||
import static java.util.concurrent.TimeUnit.MILLISECONDS; | |||
import static java.util.concurrent.TimeUnit.MINUTES; | |||
import static java.util.concurrent.TimeUnit.SECONDS; | |||
import static org.junit.Assert.assertArrayEquals; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertFalse; | |||
@@ -64,6 +69,7 @@ import java.util.Arrays; | |||
import java.util.Iterator; | |||
import java.util.LinkedList; | |||
import java.util.Set; | |||
import java.util.concurrent.TimeUnit; | |||
import org.eclipse.jgit.api.MergeCommand.FastForwardMode; | |||
import org.eclipse.jgit.errors.ConfigInvalidException; | |||
@@ -870,4 +876,93 @@ public class ConfigTest { | |||
c.fromText(content); | |||
return c; | |||
} | |||
@Test | |||
public void testTimeUnit() throws ConfigInvalidException { | |||
assertEquals(0, parseTime("0", MILLISECONDS)); | |||
assertEquals(2, parseTime("2ms", MILLISECONDS)); | |||
assertEquals(200, parseTime("200 milliseconds", MILLISECONDS)); | |||
assertEquals(0, parseTime("0s", SECONDS)); | |||
assertEquals(2, parseTime("2s", SECONDS)); | |||
assertEquals(231, parseTime("231sec", SECONDS)); | |||
assertEquals(1, parseTime("1second", SECONDS)); | |||
assertEquals(300, parseTime("300 seconds", SECONDS)); | |||
assertEquals(2, parseTime("2m", MINUTES)); | |||
assertEquals(2, parseTime("2min", MINUTES)); | |||
assertEquals(1, parseTime("1 minute", MINUTES)); | |||
assertEquals(10, parseTime("10 minutes", MINUTES)); | |||
assertEquals(5, parseTime("5h", HOURS)); | |||
assertEquals(5, parseTime("5hr", HOURS)); | |||
assertEquals(1, parseTime("1hour", HOURS)); | |||
assertEquals(48, parseTime("48hours", HOURS)); | |||
assertEquals(5, parseTime("5 h", HOURS)); | |||
assertEquals(5, parseTime("5 hr", HOURS)); | |||
assertEquals(1, parseTime("1 hour", HOURS)); | |||
assertEquals(48, parseTime("48 hours", HOURS)); | |||
assertEquals(48, parseTime("48 \t \r hours", HOURS)); | |||
assertEquals(4, parseTime("4d", DAYS)); | |||
assertEquals(1, parseTime("1day", DAYS)); | |||
assertEquals(14, parseTime("14days", DAYS)); | |||
assertEquals(7, parseTime("1w", DAYS)); | |||
assertEquals(7, parseTime("1week", DAYS)); | |||
assertEquals(14, parseTime("2w", DAYS)); | |||
assertEquals(14, parseTime("2weeks", DAYS)); | |||
assertEquals(30, parseTime("1mon", DAYS)); | |||
assertEquals(30, parseTime("1month", DAYS)); | |||
assertEquals(60, parseTime("2mon", DAYS)); | |||
assertEquals(60, parseTime("2months", DAYS)); | |||
assertEquals(365, parseTime("1y", DAYS)); | |||
assertEquals(365, parseTime("1year", DAYS)); | |||
assertEquals(365 * 2, parseTime("2years", DAYS)); | |||
} | |||
private long parseTime(String value, TimeUnit unit) | |||
throws ConfigInvalidException { | |||
Config c = parse("[a]\na=" + value + "\n"); | |||
return c.getTimeUnit("a", null, "a", 0, unit); | |||
} | |||
@Test | |||
public void testTimeUnitDefaultValue() throws ConfigInvalidException { | |||
// value not present | |||
assertEquals(20, parse("[a]\na=0\n").getTimeUnit("a", null, "b", 20, | |||
MILLISECONDS)); | |||
// value is empty | |||
assertEquals(20, parse("[a]\na=\" \"\n").getTimeUnit("a", null, "a", 20, | |||
MILLISECONDS)); | |||
// value is not numeric | |||
assertEquals(20, parse("[a]\na=test\n").getTimeUnit("a", null, "a", 20, | |||
MILLISECONDS)); | |||
} | |||
@Test | |||
public void testTimeUnitInvalid() throws ConfigInvalidException { | |||
expectedEx.expect(IllegalArgumentException.class); | |||
expectedEx | |||
.expectMessage("Invalid time unit value: a.a=1 monttthhh"); | |||
parseTime("1 monttthhh", DAYS); | |||
} | |||
@Test | |||
public void testTimeUnitInvalidWithSection() throws ConfigInvalidException { | |||
Config c = parse("[a \"b\"]\na=1 monttthhh\n"); | |||
expectedEx.expect(IllegalArgumentException.class); | |||
expectedEx.expectMessage("Invalid time unit value: a.b.a=1 monttthhh"); | |||
c.getTimeUnit("a", "b", "a", 0, DAYS); | |||
} | |||
@Test | |||
public void testTimeUnitNegative() throws ConfigInvalidException { | |||
expectedEx.expect(IllegalArgumentException.class); | |||
parseTime("-1", MILLISECONDS); | |||
} | |||
} |
@@ -1,5 +1,13 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
<component id="org.eclipse.jgit" version="2"> | |||
<resource path="META-INF/MANIFEST.MF"> | |||
<filter id="924844039"> | |||
<message_arguments> | |||
<message_argument value="4.4.1"/> | |||
<message_argument value="4.4.0"/> | |||
</message_arguments> | |||
</filter> | |||
</resource> | |||
<resource path="src/org/eclipse/jgit/attributes/AttributesNode.java" type="org.eclipse.jgit.attributes.AttributesNode"> | |||
<filter comment="moved to new AttributesManager" id="338792546"> | |||
<message_arguments> |
@@ -360,6 +360,8 @@ invalidShallowObject=invalid shallow object {0}, expected commit | |||
invalidStageForPath=Invalid stage {0} for path {1} | |||
invalidTagOption=Invalid tag option: {0} | |||
invalidTimeout=Invalid timeout: {0} | |||
invalidTimeUnitValue2=Invalid time unit value: {0}.{1}={2} | |||
invalidTimeUnitValue3=Invalid time unit value: {0}.{1}.{2}={3} | |||
invalidURL=Invalid URL {0} | |||
invalidWildcards=Invalid wildcards {0} | |||
invalidRefSpec=Invalid refspec {0} |
@@ -418,6 +418,8 @@ public class JGitText extends TranslationBundle { | |||
/***/ public String invalidStageForPath; | |||
/***/ public String invalidTagOption; | |||
/***/ public String invalidTimeout; | |||
/***/ public String invalidTimeUnitValue2; | |||
/***/ public String invalidTimeUnitValue3; | |||
/***/ public String invalidURL; | |||
/***/ public String invalidWildcards; | |||
/***/ public String invalidRefSpec; |
@@ -59,7 +59,10 @@ import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.List; | |||
import java.util.Set; | |||
import java.util.concurrent.TimeUnit; | |||
import java.util.concurrent.atomic.AtomicReference; | |||
import java.util.regex.Matcher; | |||
import java.util.regex.Pattern; | |||
import org.eclipse.jgit.errors.ConfigInvalidException; | |||
import org.eclipse.jgit.events.ConfigChangedEvent; | |||
@@ -490,6 +493,123 @@ public class Config { | |||
return res; | |||
} | |||
/** | |||
* Parse a numerical time unit, such as "1 minute", from the configuration. | |||
* | |||
* @param section | |||
* section the key is in. | |||
* @param subsection | |||
* subsection the key is in, or null if not in a subsection. | |||
* @param name | |||
* the key name. | |||
* @param defaultValue | |||
* default value to return if no value was present. | |||
* @param wantUnit | |||
* the units of {@code defaultValue} and the return value, as | |||
* well as the units to assume if the value does not contain an | |||
* indication of the units. | |||
* @return the value, or {@code defaultValue} if not set, expressed in | |||
* {@code units}. | |||
* @since 4.4 | |||
*/ | |||
public long getTimeUnit(String section, String subsection, String name, | |||
long defaultValue, TimeUnit wantUnit) { | |||
String valueString = getString(section, subsection, name); | |||
if (valueString == null) { | |||
return defaultValue; | |||
} | |||
String s = valueString.trim(); | |||
if (s.length() == 0) { | |||
return defaultValue; | |||
} | |||
if (s.startsWith("-")/* negative */) { //$NON-NLS-1$ | |||
throw notTimeUnit(section, subsection, name, valueString); | |||
} | |||
Matcher m = Pattern.compile("^(0|[1-9][0-9]*)\\s*(.*)$") //$NON-NLS-1$ | |||
.matcher(valueString); | |||
if (!m.matches()) { | |||
return defaultValue; | |||
} | |||
String digits = m.group(1); | |||
String unitName = m.group(2).trim(); | |||
TimeUnit inputUnit; | |||
int inputMul; | |||
if (unitName.isEmpty()) { | |||
inputUnit = wantUnit; | |||
inputMul = 1; | |||
} else if (match(unitName, "ms", "milliseconds")) { //$NON-NLS-1$ //$NON-NLS-2$ | |||
inputUnit = TimeUnit.MILLISECONDS; | |||
inputMul = 1; | |||
} else if (match(unitName, "s", "sec", "second", "seconds")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ | |||
inputUnit = TimeUnit.SECONDS; | |||
inputMul = 1; | |||
} else if (match(unitName, "m", "min", "minute", "minutes")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ | |||
inputUnit = TimeUnit.MINUTES; | |||
inputMul = 1; | |||
} else if (match(unitName, "h", "hr", "hour", "hours")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ | |||
inputUnit = TimeUnit.HOURS; | |||
inputMul = 1; | |||
} else if (match(unitName, "d", "day", "days")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ | |||
inputUnit = TimeUnit.DAYS; | |||
inputMul = 1; | |||
} else if (match(unitName, "w", "week", "weeks")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ | |||
inputUnit = TimeUnit.DAYS; | |||
inputMul = 7; | |||
} else if (match(unitName, "mon", "month", "months")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ | |||
inputUnit = TimeUnit.DAYS; | |||
inputMul = 30; | |||
} else if (match(unitName, "y", "year", "years")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ | |||
inputUnit = TimeUnit.DAYS; | |||
inputMul = 365; | |||
} else { | |||
throw notTimeUnit(section, subsection, name, valueString); | |||
} | |||
try { | |||
return wantUnit.convert(Long.parseLong(digits) * inputMul, | |||
inputUnit); | |||
} catch (NumberFormatException nfe) { | |||
throw notTimeUnit(section, subsection, unitName, valueString); | |||
} | |||
} | |||
private static boolean match(final String a, final String... cases) { | |||
for (final String b : cases) { | |||
if (b != null && b.equalsIgnoreCase(a)) { | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
private IllegalArgumentException notTimeUnit(String section, | |||
String subsection, String name, String valueString) { | |||
if (subsection != null) { | |||
return new IllegalArgumentException( | |||
MessageFormat.format(JGitText.get().invalidTimeUnitValue3, | |||
section, subsection, name, valueString)); | |||
} | |||
return new IllegalArgumentException( | |||
MessageFormat.format(JGitText.get().invalidTimeUnitValue2, | |||
section, name, valueString)); | |||
} | |||
/** | |||
* @param section | |||
* section to search for. |