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.Ref;
|
||||
import org.eclipse.jgit.transport.RefSpec.WildcardMode;
|
||||
import org.junit.Test;
|
||||
|
||||
public class RefSpecTest {
|
||||
|
@ -474,4 +475,28 @@ public void invalidSetDestination() {
|
|||
RefSpec a = new RefSpec("refs/heads/*: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.
|
||||
invalidCommitParentNumber=Invalid commit parent number
|
||||
invalidEncryption=Invalid encryption
|
||||
invalidExpandWildcard=ExpandFromSource on a refspec that can have mismatched wildcards does not make sense.
|
||||
invalidGitdirRef = Invalid .git reference in file ''{0}''
|
||||
invalidGitType=invalid git type: {0}
|
||||
invalidId=Invalid id: {0}
|
||||
|
|
|
@ -392,6 +392,7 @@ public static JGitText get() {
|
|||
/***/ public String invalidCharacterInBase64Data;
|
||||
/***/ public String invalidCommitParentNumber;
|
||||
/***/ public String invalidEncryption;
|
||||
/***/ public String invalidExpandWildcard;
|
||||
/***/ public String invalidGitdirRef;
|
||||
/***/ public String invalidGitType;
|
||||
/***/ public String invalidId;
|
||||
|
|
|
@ -82,6 +82,12 @@ public static boolean isWildcard(final String s) {
|
|||
/** Is this specification actually a wildcard match? */
|
||||
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. */
|
||||
private String srcName;
|
||||
|
||||
|
@ -99,6 +105,83 @@ public RefSpec() {
|
|||
wildcard = false;
|
||||
srcName = Constants.HEAD;
|
||||
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.
|
||||
*/
|
||||
public RefSpec(final String spec) {
|
||||
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))
|
||||
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);
|
||||
}
|
||||
this(spec, WildcardMode.REQUIRE_MATCH);
|
||||
}
|
||||
|
||||
private RefSpec(final RefSpec p) {
|
||||
|
@ -159,6 +213,7 @@ private RefSpec(final RefSpec p) {
|
|||
wildcard = p.isWildcard();
|
||||
srcName = p.getSource();
|
||||
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
|
||||
* specification is wildcard if and only if provided ref name is
|
||||
* wildcard.
|
||||
* @throws IllegalStateException
|
||||
* when the RefSpec was constructed with wildcard mode that
|
||||
* doesn't require matching wildcards.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -373,6 +435,9 @@ private RefSpec expandFromSourceImp(final String name) {
|
|||
* @return a new specification expanded from provided ref name. Result
|
||||
* specification is wildcard if and only if provided ref name is
|
||||
* wildcard.
|
||||
* @throws IllegalStateException
|
||||
* when the RefSpec was constructed with wildcard mode that
|
||||
* doesn't require matching wildcards.
|
||||
*/
|
||||
public RefSpec expandFromSource(final Ref r) {
|
||||
return expandFromSource(r.getName());
|
||||
|
@ -390,8 +455,15 @@ public RefSpec expandFromSource(final Ref r) {
|
|||
* @return a new specification expanded from provided ref name. Result
|
||||
* specification is wildcard if and only if provided ref name is
|
||||
* wildcard.
|
||||
* @throws IllegalStateException
|
||||
* when the RefSpec was constructed with wildcard mode that
|
||||
* doesn't require matching wildcards.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -414,6 +486,9 @@ private RefSpec expandFromDstImp(final String name) {
|
|||
* @return a new specification expanded from provided ref name. Result
|
||||
* specification is wildcard if and only if provided ref name is
|
||||
* wildcard.
|
||||
* @throws IllegalStateException
|
||||
* when the RefSpec was constructed with wildcard mode that
|
||||
* doesn't require matching wildcards.
|
||||
*/
|
||||
public RefSpec expandFromDestination(final Ref r) {
|
||||
return expandFromDestination(r.getName());
|
||||
|
@ -422,7 +497,7 @@ public RefSpec expandFromDestination(final Ref r) {
|
|||
private boolean match(final String name, final String s) {
|
||||
if (s == null)
|
||||
return false;
|
||||
if (isWildcard()) {
|
||||
if (isWildcard(s)) {
|
||||
int wildcardIndex = s.indexOf('*');
|
||||
String prefix = s.substring(0, wildcardIndex);
|
||||
String suffix = s.substring(wildcardIndex + 1);
|
||||
|
|
Loading…
Reference in New Issue