RefSpecs: allow construction of weird wildcarded RefSpecs
Gerrit's superproject subscription feature uses RefSpecs to formalize the ACLs of when the superproject subscription feature is allowed. As this is a slightly different use case than describing a local/remote pair of refs, we need to be more permissive. Specifically we want to allow: refs/heads/* refs/heads/*:refs/heads/master refs/heads/master:refs/heads/* Introduce a new constructor, that allows constructing these RefSpecs. Change-Id: I46c0bea9d876e61eb2c8d50f404b905792bc72b3 Signed-off-by: Stefan Beller <sbeller@google.com>
This commit is contained in:
parent
1556ca740b
commit
a2d3c376a6
|
@ -55,6 +55,7 @@
|
||||||
|
|
||||||
import org.eclipse.jgit.lib.ObjectIdRef;
|
import org.eclipse.jgit.lib.ObjectIdRef;
|
||||||
import org.eclipse.jgit.lib.Ref;
|
import org.eclipse.jgit.lib.Ref;
|
||||||
|
import org.eclipse.jgit.transport.RefSpec.WildcardMode;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class RefSpecTest {
|
public class RefSpecTest {
|
||||||
|
@ -474,4 +475,28 @@ public void invalidSetDestination() {
|
||||||
RefSpec a = new RefSpec("refs/heads/*:refs/remotes/origin/*");
|
RefSpec a = new RefSpec("refs/heads/*:refs/remotes/origin/*");
|
||||||
a.setDestination("refs/remotes/origin/*/*");
|
a.setDestination("refs/remotes/origin/*/*");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sourceOnlywithWildcard() {
|
||||||
|
RefSpec a = new RefSpec("refs/heads/*",
|
||||||
|
WildcardMode.ALLOW_MISMATCH);
|
||||||
|
assertTrue(a.matchSource("refs/heads/master"));
|
||||||
|
assertNull(a.getDestination());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void destinationWithWildcard() {
|
||||||
|
RefSpec a = new RefSpec("refs/heads/master:refs/heads/*",
|
||||||
|
WildcardMode.ALLOW_MISMATCH);
|
||||||
|
assertTrue(a.matchSource("refs/heads/master"));
|
||||||
|
assertTrue(a.matchDestination("refs/heads/master"));
|
||||||
|
assertTrue(a.matchDestination("refs/heads/foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onlyWildCard() {
|
||||||
|
RefSpec a = new RefSpec("*", WildcardMode.ALLOW_MISMATCH);
|
||||||
|
assertTrue(a.matchSource("refs/heads/master"));
|
||||||
|
assertNull(a.getDestination());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -333,6 +333,7 @@ invalidChannel=Invalid channel {0}
|
||||||
invalidCharacterInBase64Data=Invalid character in Base64 data.
|
invalidCharacterInBase64Data=Invalid character in Base64 data.
|
||||||
invalidCommitParentNumber=Invalid commit parent number
|
invalidCommitParentNumber=Invalid commit parent number
|
||||||
invalidEncryption=Invalid encryption
|
invalidEncryption=Invalid encryption
|
||||||
|
invalidExpandWildcard=ExpandFromSource on a refspec that can have mismatched wildcards does not make sense.
|
||||||
invalidGitdirRef = Invalid .git reference in file ''{0}''
|
invalidGitdirRef = Invalid .git reference in file ''{0}''
|
||||||
invalidGitType=invalid git type: {0}
|
invalidGitType=invalid git type: {0}
|
||||||
invalidId=Invalid id: {0}
|
invalidId=Invalid id: {0}
|
||||||
|
|
|
@ -392,6 +392,7 @@ public static JGitText get() {
|
||||||
/***/ public String invalidCharacterInBase64Data;
|
/***/ public String invalidCharacterInBase64Data;
|
||||||
/***/ public String invalidCommitParentNumber;
|
/***/ public String invalidCommitParentNumber;
|
||||||
/***/ public String invalidEncryption;
|
/***/ public String invalidEncryption;
|
||||||
|
/***/ public String invalidExpandWildcard;
|
||||||
/***/ public String invalidGitdirRef;
|
/***/ public String invalidGitdirRef;
|
||||||
/***/ public String invalidGitType;
|
/***/ public String invalidGitType;
|
||||||
/***/ public String invalidId;
|
/***/ public String invalidId;
|
||||||
|
|
|
@ -82,6 +82,12 @@ public static boolean isWildcard(final String s) {
|
||||||
/** Is this specification actually a wildcard match? */
|
/** Is this specification actually a wildcard match? */
|
||||||
private boolean wildcard;
|
private boolean wildcard;
|
||||||
|
|
||||||
|
enum WildcardMode {
|
||||||
|
REQUIRE_MATCH, ALLOW_MISMATCH
|
||||||
|
}
|
||||||
|
/** Whether a wildcard is allowed on one side but not the other. */
|
||||||
|
private WildcardMode allowMismatchedWildcards;
|
||||||
|
|
||||||
/** Name of the ref(s) we would copy from. */
|
/** Name of the ref(s) we would copy from. */
|
||||||
private String srcName;
|
private String srcName;
|
||||||
|
|
||||||
|
@ -99,6 +105,83 @@ public RefSpec() {
|
||||||
wildcard = false;
|
wildcard = false;
|
||||||
srcName = Constants.HEAD;
|
srcName = Constants.HEAD;
|
||||||
dstName = null;
|
dstName = null;
|
||||||
|
allowMismatchedWildcards = WildcardMode.REQUIRE_MATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a ref specification for use during transport operations.
|
||||||
|
* <p>
|
||||||
|
* Specifications are typically one of the following forms:
|
||||||
|
* <ul>
|
||||||
|
* <li><code>refs/heads/master</code></li>
|
||||||
|
* <li><code>refs/heads/master:refs/remotes/origin/master</code></li>
|
||||||
|
* <li><code>refs/heads/*:refs/remotes/origin/*</code></li>
|
||||||
|
* <li><code>+refs/heads/master</code></li>
|
||||||
|
* <li><code>+refs/heads/master:refs/remotes/origin/master</code></li>
|
||||||
|
* <li><code>+refs/heads/*:refs/remotes/origin/*</code></li>
|
||||||
|
* <li><code>+refs/pull/*/head:refs/remotes/origin/pr/*</code></li>
|
||||||
|
* <li><code>:refs/heads/master</code></li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* If the wildcard mode allows mismatches, then these ref specs are also
|
||||||
|
* valid:
|
||||||
|
* <ul>
|
||||||
|
* <li><code>refs/heads/*</code></li>
|
||||||
|
* <li><code>refs/heads/*:refs/heads/master</code></li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param spec
|
||||||
|
* string describing the specification.
|
||||||
|
* @param mode
|
||||||
|
* whether to allow a wildcard on one side without a wildcard on
|
||||||
|
* the other.
|
||||||
|
* @throws IllegalArgumentException
|
||||||
|
* the specification is invalid.
|
||||||
|
* @since 4.5
|
||||||
|
*/
|
||||||
|
public RefSpec(String spec, WildcardMode mode) {
|
||||||
|
this.allowMismatchedWildcards = mode;
|
||||||
|
String s = spec;
|
||||||
|
if (s.startsWith("+")) { //$NON-NLS-1$
|
||||||
|
force = true;
|
||||||
|
s = s.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
final int c = s.lastIndexOf(':');
|
||||||
|
if (c == 0) {
|
||||||
|
s = s.substring(1);
|
||||||
|
if (isWildcard(s)) {
|
||||||
|
wildcard = true;
|
||||||
|
if (mode == WildcardMode.REQUIRE_MATCH) {
|
||||||
|
throw new IllegalArgumentException(MessageFormat
|
||||||
|
.format(JGitText.get().invalidWildcards, spec));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dstName = checkValid(s);
|
||||||
|
} else if (c > 0) {
|
||||||
|
String src = s.substring(0, c);
|
||||||
|
String dst = s.substring(c + 1);
|
||||||
|
if (isWildcard(src) && isWildcard(dst)) {
|
||||||
|
// Both contain wildcard
|
||||||
|
wildcard = true;
|
||||||
|
} else if (isWildcard(src) || isWildcard(dst)) {
|
||||||
|
wildcard = true;
|
||||||
|
if (mode == WildcardMode.REQUIRE_MATCH)
|
||||||
|
throw new IllegalArgumentException(MessageFormat
|
||||||
|
.format(JGitText.get().invalidWildcards, spec));
|
||||||
|
}
|
||||||
|
srcName = checkValid(src);
|
||||||
|
dstName = checkValid(dst);
|
||||||
|
} else {
|
||||||
|
if (isWildcard(s)) {
|
||||||
|
if (mode == WildcardMode.REQUIRE_MATCH) {
|
||||||
|
throw new IllegalArgumentException(MessageFormat
|
||||||
|
.format(JGitText.get().invalidWildcards, spec));
|
||||||
|
}
|
||||||
|
wildcard = true;
|
||||||
|
}
|
||||||
|
srcName = checkValid(s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -122,36 +205,7 @@ public RefSpec() {
|
||||||
* the specification is invalid.
|
* the specification is invalid.
|
||||||
*/
|
*/
|
||||||
public RefSpec(final String spec) {
|
public RefSpec(final String spec) {
|
||||||
String s = spec;
|
this(spec, WildcardMode.REQUIRE_MATCH);
|
||||||
if (s.startsWith("+")) { //$NON-NLS-1$
|
|
||||||
force = true;
|
|
||||||
s = s.substring(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
final int c = s.lastIndexOf(':');
|
|
||||||
if (c == 0) {
|
|
||||||
s = s.substring(1);
|
|
||||||
if (isWildcard(s))
|
|
||||||
throw new IllegalArgumentException(MessageFormat.format(JGitText.get().invalidWildcards, spec));
|
|
||||||
dstName = checkValid(s);
|
|
||||||
} else if (c > 0) {
|
|
||||||
String src = s.substring(0, c);
|
|
||||||
String dst = s.substring(c + 1);
|
|
||||||
if (isWildcard(src) && isWildcard(dst)) {
|
|
||||||
// Both contain wildcard
|
|
||||||
wildcard = true;
|
|
||||||
} else if (isWildcard(src) || isWildcard(dst)) {
|
|
||||||
// If either source or destination has wildcard, the other one
|
|
||||||
// must have as well.
|
|
||||||
throw new IllegalArgumentException(MessageFormat.format(JGitText.get().invalidWildcards, spec));
|
|
||||||
}
|
|
||||||
srcName = checkValid(src);
|
|
||||||
dstName = checkValid(dst);
|
|
||||||
} else {
|
|
||||||
if (isWildcard(s))
|
|
||||||
throw new IllegalArgumentException(MessageFormat.format(JGitText.get().invalidWildcards, spec));
|
|
||||||
srcName = checkValid(s);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private RefSpec(final RefSpec p) {
|
private RefSpec(final RefSpec p) {
|
||||||
|
@ -159,6 +213,7 @@ private RefSpec(final RefSpec p) {
|
||||||
wildcard = p.isWildcard();
|
wildcard = p.isWildcard();
|
||||||
srcName = p.getSource();
|
srcName = p.getSource();
|
||||||
dstName = p.getDestination();
|
dstName = p.getDestination();
|
||||||
|
allowMismatchedWildcards = p.allowMismatchedWildcards;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -348,8 +403,15 @@ public boolean matchDestination(final Ref r) {
|
||||||
* @return a new specification expanded from provided ref name. Result
|
* @return a new specification expanded from provided ref name. Result
|
||||||
* specification is wildcard if and only if provided ref name is
|
* specification is wildcard if and only if provided ref name is
|
||||||
* wildcard.
|
* wildcard.
|
||||||
|
* @throws IllegalStateException
|
||||||
|
* when the RefSpec was constructed with wildcard mode that
|
||||||
|
* doesn't require matching wildcards.
|
||||||
*/
|
*/
|
||||||
public RefSpec expandFromSource(final String r) {
|
public RefSpec expandFromSource(final String r) {
|
||||||
|
if (allowMismatchedWildcards != WildcardMode.REQUIRE_MATCH) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
JGitText.get().invalidExpandWildcard);
|
||||||
|
}
|
||||||
return isWildcard() ? new RefSpec(this).expandFromSourceImp(r) : this;
|
return isWildcard() ? new RefSpec(this).expandFromSourceImp(r) : this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,6 +435,9 @@ private RefSpec expandFromSourceImp(final String name) {
|
||||||
* @return a new specification expanded from provided ref name. Result
|
* @return a new specification expanded from provided ref name. Result
|
||||||
* specification is wildcard if and only if provided ref name is
|
* specification is wildcard if and only if provided ref name is
|
||||||
* wildcard.
|
* wildcard.
|
||||||
|
* @throws IllegalStateException
|
||||||
|
* when the RefSpec was constructed with wildcard mode that
|
||||||
|
* doesn't require matching wildcards.
|
||||||
*/
|
*/
|
||||||
public RefSpec expandFromSource(final Ref r) {
|
public RefSpec expandFromSource(final Ref r) {
|
||||||
return expandFromSource(r.getName());
|
return expandFromSource(r.getName());
|
||||||
|
@ -390,8 +455,15 @@ public RefSpec expandFromSource(final Ref r) {
|
||||||
* @return a new specification expanded from provided ref name. Result
|
* @return a new specification expanded from provided ref name. Result
|
||||||
* specification is wildcard if and only if provided ref name is
|
* specification is wildcard if and only if provided ref name is
|
||||||
* wildcard.
|
* wildcard.
|
||||||
|
* @throws IllegalStateException
|
||||||
|
* when the RefSpec was constructed with wildcard mode that
|
||||||
|
* doesn't require matching wildcards.
|
||||||
*/
|
*/
|
||||||
public RefSpec expandFromDestination(final String r) {
|
public RefSpec expandFromDestination(final String r) {
|
||||||
|
if (allowMismatchedWildcards != WildcardMode.REQUIRE_MATCH) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
JGitText.get().invalidExpandWildcard);
|
||||||
|
}
|
||||||
return isWildcard() ? new RefSpec(this).expandFromDstImp(r) : this;
|
return isWildcard() ? new RefSpec(this).expandFromDstImp(r) : this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,6 +486,9 @@ private RefSpec expandFromDstImp(final String name) {
|
||||||
* @return a new specification expanded from provided ref name. Result
|
* @return a new specification expanded from provided ref name. Result
|
||||||
* specification is wildcard if and only if provided ref name is
|
* specification is wildcard if and only if provided ref name is
|
||||||
* wildcard.
|
* wildcard.
|
||||||
|
* @throws IllegalStateException
|
||||||
|
* when the RefSpec was constructed with wildcard mode that
|
||||||
|
* doesn't require matching wildcards.
|
||||||
*/
|
*/
|
||||||
public RefSpec expandFromDestination(final Ref r) {
|
public RefSpec expandFromDestination(final Ref r) {
|
||||||
return expandFromDestination(r.getName());
|
return expandFromDestination(r.getName());
|
||||||
|
@ -422,7 +497,7 @@ public RefSpec expandFromDestination(final Ref r) {
|
||||||
private boolean match(final String name, final String s) {
|
private boolean match(final String name, final String s) {
|
||||||
if (s == null)
|
if (s == null)
|
||||||
return false;
|
return false;
|
||||||
if (isWildcard()) {
|
if (isWildcard(s)) {
|
||||||
int wildcardIndex = s.indexOf('*');
|
int wildcardIndex = s.indexOf('*');
|
||||||
String prefix = s.substring(0, wildcardIndex);
|
String prefix = s.substring(0, wildcardIndex);
|
||||||
String suffix = s.substring(wildcardIndex + 1);
|
String suffix = s.substring(wildcardIndex + 1);
|
||||||
|
|
Loading…
Reference in New Issue