SubmoduleOp: Allow all branches to be subscribed
This eases the way of handling many different branches for the superproject subscription. As the superproject subscriptions are not yet in a release, we can still play around with them. When a user sees "refs = refs/heads/*:refs/heads/*" they cannot tell whether this is 1:1 matching or any match to any match without consulting the documentation. Differentiate the matching strategy by keys, such that we have "all = <refspec>" as well as "matching = <refspec>". The "all" key implies there is no interaction between the wildcards on the left and right side, e.g. all=refs/heads/*:refs/heads* indicates that any branch can be subscribed to any other branch in the given superproject. "matching" however substitutes the wildcard on the right with the captured value on the left. matching=refs/heads/*:refs/heads* allows a subscription of refs/heads/foo in the submodule to the refs/heads/foo in the superproject. Change-Id: I84d3a72c00f76570798880adf54ce56f974466ff
This commit is contained in:
@@ -86,7 +86,7 @@ the subscribe capabilities in the 'project.config' file:
|
||||
and add the following lines:
|
||||
----
|
||||
[allowSuperproject "<superproject>"]
|
||||
refs = <refspec>
|
||||
matching = <refspec>
|
||||
----
|
||||
where the 'superproject' should be the exact project name of the superproject.
|
||||
The refspec defines which branches of the submodule are allowed to be
|
||||
@@ -104,7 +104,7 @@ The configuration is inherited from parent projects, such that you can have
|
||||
a configuration in the "All-Projects" project like:
|
||||
----
|
||||
[allowSuperproject "my-only-superproject"]
|
||||
refs = refs/heads/*:refs/heads/*
|
||||
matching = refs/heads/*:refs/heads/*
|
||||
----
|
||||
and then you don't have to worry about configuring the individual projects
|
||||
any more. Child projects cannot negate the parent's configuration.
|
||||
@@ -147,14 +147,17 @@ a `branch` field and a url pointing to this server.
|
||||
|
||||
[[acl_refspec]]
|
||||
=== The RefSpec in the allowSuperproject section
|
||||
The RefSpec for defining the branch level access for subscriptions look similar
|
||||
to Git style RefSpecs used for pushing in Git. Regular expressions
|
||||
as found in the ACL configuration are not supported. The most restrictive
|
||||
RefSpec is allowing one specific branch of the submodule to be subscribed
|
||||
to one specific branch of the superproject via:
|
||||
There are two options for specifying which branches can be subscribed
|
||||
to. The most common is to set `allowSuperproject.<superproject>.matching`
|
||||
to a Git-style refspec, which has the same syntax as the refspecs used
|
||||
for pushing in Git. Regular expressions as found in the ACL configuration
|
||||
are not supported.
|
||||
|
||||
The most restrictive refspec is allowing one specific branch of the
|
||||
submodule to be subscribed to one specific branch of the superproject:
|
||||
----
|
||||
[allowSuperproject "<superproject>"]
|
||||
refs = refs/heads/<submodule-branch>:refs/heads/<superproject-branch>
|
||||
matching = refs/heads/<submodule-branch>:refs/heads/<superproject-branch>
|
||||
----
|
||||
|
||||
If you want to allow for a 1:1 mapping, i.e. 'master' maps to 'master',
|
||||
@@ -162,14 +165,24 @@ If you want to allow for a 1:1 mapping, i.e. 'master' maps to 'master',
|
||||
'stable':
|
||||
----
|
||||
[allowSuperproject "<superproject>"]
|
||||
refs = refs/heads/*:refs/heads/*
|
||||
matching = refs/heads/*:refs/heads/*
|
||||
----
|
||||
|
||||
If you want to enable a branch to be subscribed to any other branch of
|
||||
the superproject, omit the second part of the RefSpec:
|
||||
To allow all refs matching one pattern to subscribe to all refs
|
||||
matching another pattern, set `allowSuperproject.<superproject>.all`
|
||||
to the patterns concatenated with a colon. For example, to make a
|
||||
single branch available for subscription from all branches of the
|
||||
superproject:
|
||||
----
|
||||
[allowSuperproject "<superproject>"]
|
||||
refs = refs/heads/<submodule-branch>
|
||||
all = refs/heads/<submodule-branch>:refs/heads/*
|
||||
----
|
||||
|
||||
To make all branches available for subscription from all branches of
|
||||
the superproject:
|
||||
----
|
||||
[allowSuperproject "<superproject>"]
|
||||
all = refs/heads/*:refs/heads/*
|
||||
----
|
||||
|
||||
=== Subscription Limitations
|
||||
|
||||
@@ -130,18 +130,25 @@ public abstract class AbstractSubmoduleSubscription extends AbstractDaemonTest {
|
||||
return pushChangeTo(repo, "refs/heads/" + branch, "some change", "");
|
||||
}
|
||||
|
||||
protected void allowSubmoduleSubscription(String submodule, String subBranch,
|
||||
String superproject, String superBranch) throws Exception {
|
||||
protected void allowSubmoduleSubscription(String submodule,
|
||||
String subBranch, String superproject, String superBranch, boolean match)
|
||||
throws Exception {
|
||||
Project.NameKey sub = new Project.NameKey(name(submodule));
|
||||
Project.NameKey superName = new Project.NameKey(name(superproject));
|
||||
try (MetaDataUpdate md = metaDataUpdateFactory.create(sub)) {
|
||||
md.setMessage("Added superproject subscription");
|
||||
ProjectConfig pc = ProjectConfig.read(md);
|
||||
SubscribeSection s = new SubscribeSection(superName);
|
||||
String refspec;
|
||||
if (superBranch == null) {
|
||||
s.addRefSpec(subBranch);
|
||||
refspec = subBranch;
|
||||
} else {
|
||||
s.addRefSpec(subBranch + ":" + superBranch);
|
||||
refspec = subBranch + ":" + superBranch;
|
||||
}
|
||||
if (match) {
|
||||
s.addMatchingRefSpec(refspec);
|
||||
} else {
|
||||
s.addMultiMatchRefSpec(refspec);
|
||||
}
|
||||
pc.addSubscribeSection(s);
|
||||
ObjectId oldId = pc.getRevision();
|
||||
@@ -151,6 +158,13 @@ public abstract class AbstractSubmoduleSubscription extends AbstractDaemonTest {
|
||||
}
|
||||
}
|
||||
|
||||
protected void allowMatchingSubmoduleSubscription(String submodule,
|
||||
String subBranch, String superproject, String superBranch)
|
||||
throws Exception {
|
||||
allowSubmoduleSubscription(submodule, subBranch, superproject,
|
||||
superBranch, true);
|
||||
}
|
||||
|
||||
protected void createSubmoduleSubscription(TestRepository<?> repo, String branch,
|
||||
String subscribeToRepo, String subscribeToBranch) throws Exception {
|
||||
Config config = new Config();
|
||||
|
||||
@@ -44,7 +44,7 @@ public class SubmoduleSubscriptionsIT extends AbstractSubmoduleSubscription {
|
||||
public void testSubscriptionWithoutGlobalServerSetting() throws Exception {
|
||||
TestRepository<?> superRepo = createProjectWithPush("super-project");
|
||||
TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
|
||||
allowSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
"super-project", "refs/heads/master");
|
||||
|
||||
createSubmoduleSubscription(superRepo, "master",
|
||||
@@ -70,7 +70,7 @@ public class SubmoduleSubscriptionsIT extends AbstractSubmoduleSubscription {
|
||||
public void testSubscriptionToEmptyRepo() throws Exception {
|
||||
TestRepository<?> superRepo = createProjectWithPush("super-project");
|
||||
TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
|
||||
allowSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
"super-project", "refs/heads/master");
|
||||
|
||||
createSubmoduleSubscription(superRepo, "master",
|
||||
@@ -87,7 +87,7 @@ public class SubmoduleSubscriptionsIT extends AbstractSubmoduleSubscription {
|
||||
public void testSubscriptionToExistingRepo() throws Exception {
|
||||
TestRepository<?> superRepo = createProjectWithPush("super-project");
|
||||
TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
|
||||
allowSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
"super-project", "refs/heads/master");
|
||||
|
||||
pushChangeTo(subRepo, "master");
|
||||
@@ -104,8 +104,8 @@ public class SubmoduleSubscriptionsIT extends AbstractSubmoduleSubscription {
|
||||
public void testSubscriptionWildcardACLForSingleBranch() throws Exception {
|
||||
TestRepository<?> superRepo = createProjectWithPush("super-project");
|
||||
TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
|
||||
// master is allowed to be subscribed to any superprojects branch:
|
||||
allowSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
// master is allowed to be subscribed to master branch only:
|
||||
allowMatchingSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
"super-project", null);
|
||||
// create 'branch':
|
||||
pushChangeTo(superRepo, "branch");
|
||||
@@ -120,14 +120,14 @@ public class SubmoduleSubscriptionsIT extends AbstractSubmoduleSubscription {
|
||||
|
||||
expectToHaveSubmoduleState(superRepo, "master",
|
||||
"subscribed-to-project", subHEAD);
|
||||
expectToHaveSubmoduleState(superRepo, "branch",
|
||||
"subscribed-to-project", subHEAD);
|
||||
assertThat(hasSubmodule(superRepo, "branch",
|
||||
"subscribed-to-project")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSubscriptionWildcardACLForMissingProject() throws Exception {
|
||||
TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
|
||||
allowSubmoduleSubscription("subscribed-to-project", "refs/heads/*",
|
||||
allowMatchingSubmoduleSubscription("subscribed-to-project", "refs/heads/*",
|
||||
"not-existing-super-project", "refs/heads/*");
|
||||
pushChangeTo(subRepo, "master");
|
||||
}
|
||||
@@ -136,7 +136,7 @@ public class SubmoduleSubscriptionsIT extends AbstractSubmoduleSubscription {
|
||||
public void testSubscriptionWildcardACLForMissingBranch() throws Exception {
|
||||
createProjectWithPush("super-project");
|
||||
TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
|
||||
allowSubmoduleSubscription("subscribed-to-project", "refs/heads/*",
|
||||
allowMatchingSubmoduleSubscription("subscribed-to-project", "refs/heads/*",
|
||||
"super-project", "refs/heads/*");
|
||||
pushChangeTo(subRepo, "foo");
|
||||
}
|
||||
@@ -145,7 +145,7 @@ public class SubmoduleSubscriptionsIT extends AbstractSubmoduleSubscription {
|
||||
public void testSubscriptionWildcardACLForMissingGitmodules() throws Exception {
|
||||
TestRepository<?> superRepo = createProjectWithPush("super-project");
|
||||
TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
|
||||
allowSubmoduleSubscription("subscribed-to-project", "refs/heads/*",
|
||||
allowMatchingSubmoduleSubscription("subscribed-to-project", "refs/heads/*",
|
||||
"super-project", "refs/heads/*");
|
||||
pushChangeTo(superRepo, "master");
|
||||
pushChangeTo(subRepo, "master");
|
||||
@@ -156,7 +156,7 @@ public class SubmoduleSubscriptionsIT extends AbstractSubmoduleSubscription {
|
||||
TestRepository<?> superRepo = createProjectWithPush("super-project");
|
||||
TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
|
||||
// any branch is allowed to be subscribed to the same superprojects branch:
|
||||
allowSubmoduleSubscription("subscribed-to-project", "refs/heads/*",
|
||||
allowMatchingSubmoduleSubscription("subscribed-to-project", "refs/heads/*",
|
||||
"super-project", "refs/heads/*");
|
||||
|
||||
// create 'branch' in both repos:
|
||||
@@ -188,12 +188,53 @@ public class SubmoduleSubscriptionsIT extends AbstractSubmoduleSubscription {
|
||||
"subscribed-to-project", subHEAD3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSubscriptionWildcardACLForManyBranches() throws Exception {
|
||||
TestRepository<?> superRepo = createProjectWithPush("super-project");
|
||||
TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
|
||||
|
||||
// Any branch is allowed to be subscribed to any superproject branch:
|
||||
allowSubmoduleSubscription("subscribed-to-project", "refs/heads/*",
|
||||
"super-project", null, false);
|
||||
pushChangeTo(superRepo, "branch");
|
||||
pushChangeTo(subRepo, "another-branch");
|
||||
createSubmoduleSubscription(superRepo, "branch",
|
||||
"subscribed-to-project", "another-branch");
|
||||
ObjectId subHEAD = pushChangeTo(subRepo, "another-branch");
|
||||
expectToHaveSubmoduleState(superRepo, "branch",
|
||||
"subscribed-to-project", subHEAD);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSubscriptionWildcardACLOneToManyBranches() throws Exception {
|
||||
TestRepository<?> superRepo = createProjectWithPush("super-project");
|
||||
TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
|
||||
|
||||
// Any branch is allowed to be subscribed to any superproject branch:
|
||||
allowSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
"super-project", "refs/heads/*", false);
|
||||
pushChangeTo(superRepo, "branch");
|
||||
createSubmoduleSubscription(superRepo, "branch",
|
||||
"subscribed-to-project", "master");
|
||||
ObjectId subHEAD = pushChangeTo(subRepo, "master");
|
||||
expectToHaveSubmoduleState(superRepo, "branch",
|
||||
"subscribed-to-project", subHEAD);
|
||||
|
||||
createSubmoduleSubscription(superRepo, "branch",
|
||||
"subscribed-to-project", "branch");
|
||||
pushChangeTo(subRepo, "branch");
|
||||
|
||||
// no change expected, as only master is subscribed:
|
||||
expectToHaveSubmoduleState(superRepo, "branch",
|
||||
"subscribed-to-project", subHEAD);
|
||||
}
|
||||
|
||||
@Test
|
||||
@GerritConfig(name = "submodule.verboseSuperprojectUpdate", value = "false")
|
||||
public void testSubmoduleShortCommitMessage() throws Exception {
|
||||
TestRepository<?> superRepo = createProjectWithPush("super-project");
|
||||
TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
|
||||
allowSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
"super-project", "refs/heads/master");
|
||||
|
||||
pushChangeTo(subRepo, "master");
|
||||
@@ -220,7 +261,7 @@ public class SubmoduleSubscriptionsIT extends AbstractSubmoduleSubscription {
|
||||
public void testSubmoduleSubjectCommitMessage() throws Exception {
|
||||
TestRepository<?> superRepo = createProjectWithPush("super-project");
|
||||
TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
|
||||
allowSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
"super-project", "refs/heads/master");
|
||||
|
||||
pushChangeTo(subRepo, "master");
|
||||
@@ -248,7 +289,7 @@ public class SubmoduleSubscriptionsIT extends AbstractSubmoduleSubscription {
|
||||
public void testSubmoduleCommitMessage() throws Exception {
|
||||
TestRepository<?> superRepo = createProjectWithPush("super-project");
|
||||
TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
|
||||
allowSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
"super-project", "refs/heads/master");
|
||||
|
||||
pushChangeTo(subRepo, "master");
|
||||
@@ -276,7 +317,7 @@ public class SubmoduleSubscriptionsIT extends AbstractSubmoduleSubscription {
|
||||
public void testSubscriptionUnsubscribe() throws Exception {
|
||||
TestRepository<?> superRepo = createProjectWithPush("super-project");
|
||||
TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
|
||||
allowSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
"super-project", "refs/heads/master");
|
||||
|
||||
pushChangeTo(subRepo, "master");
|
||||
@@ -303,7 +344,7 @@ public class SubmoduleSubscriptionsIT extends AbstractSubmoduleSubscription {
|
||||
throws Exception {
|
||||
TestRepository<?> superRepo = createProjectWithPush("super-project");
|
||||
TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
|
||||
allowSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
"super-project", "refs/heads/master");
|
||||
|
||||
pushChangeTo(subRepo, "master");
|
||||
@@ -329,7 +370,7 @@ public class SubmoduleSubscriptionsIT extends AbstractSubmoduleSubscription {
|
||||
public void testSubscriptionToDifferentBranches() throws Exception {
|
||||
TestRepository<?> superRepo = createProjectWithPush("super-project");
|
||||
TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
|
||||
allowSubmoduleSubscription("subscribed-to-project", "refs/heads/foo",
|
||||
allowMatchingSubmoduleSubscription("subscribed-to-project", "refs/heads/foo",
|
||||
"super-project", "refs/heads/master");
|
||||
|
||||
createSubmoduleSubscription(superRepo, "master",
|
||||
@@ -345,9 +386,9 @@ public class SubmoduleSubscriptionsIT extends AbstractSubmoduleSubscription {
|
||||
public void testBranchCircularSubscription() throws Exception {
|
||||
TestRepository<?> superRepo = createProjectWithPush("super-project");
|
||||
TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
|
||||
allowSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
"super-project", "refs/heads/master");
|
||||
allowSubmoduleSubscription("super-project", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("super-project", "refs/heads/master",
|
||||
"subscribed-to-project", "refs/heads/master");
|
||||
|
||||
pushChangeTo(subRepo, "master");
|
||||
@@ -370,9 +411,9 @@ public class SubmoduleSubscriptionsIT extends AbstractSubmoduleSubscription {
|
||||
TestRepository<?> superRepo = createProjectWithPush("super-project");
|
||||
TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
|
||||
|
||||
allowSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
"super-project", "refs/heads/master");
|
||||
allowSubmoduleSubscription("super-project", "refs/heads/dev",
|
||||
allowMatchingSubmoduleSubscription("super-project", "refs/heads/dev",
|
||||
"subscribed-to-project", "refs/heads/dev");
|
||||
|
||||
pushChangeTo(subRepo, "master");
|
||||
@@ -414,7 +455,7 @@ public class SubmoduleSubscriptionsIT extends AbstractSubmoduleSubscription {
|
||||
public void testSubscriptionFailOnWrongProjectACL() throws Exception {
|
||||
TestRepository<?> superRepo = createProjectWithPush("super-project");
|
||||
TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
|
||||
allowSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
"wrong-super-project", "refs/heads/master");
|
||||
|
||||
pushChangeTo(subRepo, "master");
|
||||
@@ -429,7 +470,7 @@ public class SubmoduleSubscriptionsIT extends AbstractSubmoduleSubscription {
|
||||
public void testSubscriptionFailOnWrongBranchACL() throws Exception {
|
||||
TestRepository<?> superRepo = createProjectWithPush("super-project");
|
||||
TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
|
||||
allowSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
"super-project", "refs/heads/wrong-branch");
|
||||
|
||||
pushChangeTo(subRepo, "master");
|
||||
@@ -448,7 +489,7 @@ public class SubmoduleSubscriptionsIT extends AbstractSubmoduleSubscription {
|
||||
TestRepository<?> superRepo = createProjectWithPush("super-project");
|
||||
TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project",
|
||||
new Project.NameKey(name("config-repo2")));
|
||||
allowSubmoduleSubscription("config-repo", "refs/heads/*",
|
||||
allowMatchingSubmoduleSubscription("config-repo", "refs/heads/*",
|
||||
"super-project", "refs/heads/*");
|
||||
|
||||
pushChangeTo(subRepo, "master");
|
||||
@@ -463,7 +504,7 @@ public class SubmoduleSubscriptionsIT extends AbstractSubmoduleSubscription {
|
||||
public void testAllowedButNotSubscribed() throws Exception {
|
||||
TestRepository<?> superRepo = createProjectWithPush("super-project");
|
||||
TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
|
||||
allowSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
"super-project", "refs/heads/master");
|
||||
|
||||
pushChangeTo(subRepo, "master");
|
||||
@@ -490,7 +531,7 @@ public class SubmoduleSubscriptionsIT extends AbstractSubmoduleSubscription {
|
||||
TestRepository<?> subRepo = createProjectWithPush(
|
||||
"nested/subscribed-to-project");
|
||||
// master is allowed to be subscribed to any superprojects branch:
|
||||
allowSubmoduleSubscription("nested/subscribed-to-project",
|
||||
allowMatchingSubmoduleSubscription("nested/subscribed-to-project",
|
||||
"refs/heads/master", "super-project", null);
|
||||
|
||||
pushChangeTo(subRepo, "master");
|
||||
|
||||
@@ -58,7 +58,7 @@ public class SubmoduleSubscriptionsWholeTopicMergeIT
|
||||
public void testSubscriptionUpdateOfManyChanges() throws Exception {
|
||||
TestRepository<?> superRepo = createProjectWithPush("super-project");
|
||||
TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
|
||||
allowSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
"super-project", "refs/heads/master");
|
||||
|
||||
createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "master");
|
||||
@@ -113,7 +113,7 @@ public class SubmoduleSubscriptionsWholeTopicMergeIT
|
||||
public void testSubscriptionUpdateIncludingChangeInSuperproject() throws Exception {
|
||||
TestRepository<?> superRepo = createProjectWithPush("super-project");
|
||||
TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
|
||||
allowSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
"super-project", "refs/heads/master");
|
||||
|
||||
createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "master");
|
||||
@@ -181,11 +181,11 @@ public class SubmoduleSubscriptionsWholeTopicMergeIT
|
||||
TestRepository<?> sub2 = createProjectWithPush("sub2");
|
||||
TestRepository<?> sub3 = createProjectWithPush("sub3");
|
||||
|
||||
allowSubmoduleSubscription("sub1", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("sub1", "refs/heads/master",
|
||||
"super-project", "refs/heads/master");
|
||||
allowSubmoduleSubscription("sub2", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("sub2", "refs/heads/master",
|
||||
"super-project", "refs/heads/master");
|
||||
allowSubmoduleSubscription("sub3", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("sub3", "refs/heads/master",
|
||||
"super-project", "refs/heads/master");
|
||||
|
||||
Config config = new Config();
|
||||
@@ -227,7 +227,7 @@ public class SubmoduleSubscriptionsWholeTopicMergeIT
|
||||
TestRepository<?> superRepo = createProjectWithPush("super-project");
|
||||
TestRepository<?> sub = createProjectWithPush("sub");
|
||||
|
||||
allowSubmoduleSubscription("sub", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("sub", "refs/heads/master",
|
||||
"super-project", "refs/heads/master");
|
||||
|
||||
Config config = new Config();
|
||||
@@ -261,7 +261,7 @@ public class SubmoduleSubscriptionsWholeTopicMergeIT
|
||||
TestRepository<?> sub = createProjectWithPush("sub");
|
||||
TestRepository<?> standAlone = createProjectWithPush("standalone");
|
||||
|
||||
allowSubmoduleSubscription("sub", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("sub", "refs/heads/master",
|
||||
"super-project", "refs/heads/master");
|
||||
|
||||
createSubmoduleSubscription(superRepo, "master", "sub", "master");
|
||||
@@ -301,9 +301,9 @@ public class SubmoduleSubscriptionsWholeTopicMergeIT
|
||||
TestRepository<?> midRepo = createProjectWithPush("mid-project");
|
||||
TestRepository<?> bottomRepo = createProjectWithPush("bottom-project");
|
||||
|
||||
allowSubmoduleSubscription("mid-project", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("mid-project", "refs/heads/master",
|
||||
"top-project", "refs/heads/master");
|
||||
allowSubmoduleSubscription("bottom-project", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("bottom-project", "refs/heads/master",
|
||||
"mid-project", "refs/heads/master");
|
||||
|
||||
createSubmoduleSubscription(topRepo, "master", "mid-project", "master");
|
||||
@@ -332,11 +332,11 @@ public class SubmoduleSubscriptionsWholeTopicMergeIT
|
||||
TestRepository<?> midRepo = createProjectWithPush("mid-project");
|
||||
TestRepository<?> bottomRepo = createProjectWithPush("bottom-project");
|
||||
|
||||
allowSubmoduleSubscription("mid-project", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("mid-project", "refs/heads/master",
|
||||
"top-project", "refs/heads/master");
|
||||
allowSubmoduleSubscription("bottom-project", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("bottom-project", "refs/heads/master",
|
||||
"mid-project", "refs/heads/master");
|
||||
allowSubmoduleSubscription("bottom-project", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("bottom-project", "refs/heads/master",
|
||||
"top-project", "refs/heads/master");
|
||||
|
||||
createSubmoduleSubscription(midRepo, "master", "bottom-project", "master");
|
||||
@@ -373,11 +373,11 @@ public class SubmoduleSubscriptionsWholeTopicMergeIT
|
||||
createSubmoduleSubscription(topRepo, "master", "mid-project", "master");
|
||||
createSubmoduleSubscription(bottomRepo, "master", "top-project", "master");
|
||||
|
||||
allowSubmoduleSubscription("bottom-project", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("bottom-project", "refs/heads/master",
|
||||
"mid-project", "refs/heads/master");
|
||||
allowSubmoduleSubscription("mid-project", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("mid-project", "refs/heads/master",
|
||||
"top-project", "refs/heads/master");
|
||||
allowSubmoduleSubscription("top-project", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("top-project", "refs/heads/master",
|
||||
"bottom-project", "refs/heads/master");
|
||||
|
||||
ObjectId bottomMasterHead =
|
||||
@@ -401,9 +401,9 @@ public class SubmoduleSubscriptionsWholeTopicMergeIT
|
||||
TestRepository<?> superRepo = createProjectWithPush("super-project");
|
||||
TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
|
||||
|
||||
allowSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
allowMatchingSubmoduleSubscription("subscribed-to-project", "refs/heads/master",
|
||||
"super-project", "refs/heads/master");
|
||||
allowSubmoduleSubscription("super-project", "refs/heads/dev",
|
||||
allowMatchingSubmoduleSubscription("super-project", "refs/heads/dev",
|
||||
"subscribed-to-project", "refs/heads/dev");
|
||||
|
||||
pushChangeTo(subRepo, "dev");
|
||||
|
||||
@@ -29,20 +29,28 @@ import java.util.List;
|
||||
@GwtIncompatible("Unemulated org.eclipse.jgit.transport.RefSpec")
|
||||
public class SubscribeSection {
|
||||
|
||||
private final List<RefSpec> refSpecs;
|
||||
private final List<RefSpec> multiMatchRefSpecs;
|
||||
private final List<RefSpec> matchingRefSpecs;
|
||||
private final Project.NameKey project;
|
||||
|
||||
public SubscribeSection(Project.NameKey p) {
|
||||
project = p;
|
||||
refSpecs = new ArrayList<>();
|
||||
matchingRefSpecs = new ArrayList<>();
|
||||
multiMatchRefSpecs = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void addRefSpec(RefSpec spec) {
|
||||
refSpecs.add(spec);
|
||||
public void addMatchingRefSpec(RefSpec spec) {
|
||||
matchingRefSpecs.add(spec);
|
||||
}
|
||||
|
||||
public void addRefSpec(String spec) {
|
||||
refSpecs.add(new RefSpec(spec));
|
||||
public void addMatchingRefSpec(String spec) {
|
||||
RefSpec r = new RefSpec(spec);
|
||||
matchingRefSpecs.add(r);
|
||||
}
|
||||
|
||||
public void addMultiMatchRefSpec(String spec) {
|
||||
RefSpec r = new RefSpec(spec, RefSpec.WildcardMode.ALLOW_MISMATCH);
|
||||
multiMatchRefSpecs.add(r);
|
||||
}
|
||||
|
||||
public Project.NameKey getProject() {
|
||||
@@ -57,7 +65,12 @@ public class SubscribeSection {
|
||||
* @return if the branch could trigger a superproject update
|
||||
*/
|
||||
public boolean appliesTo(Branch.NameKey branch) {
|
||||
for (RefSpec r : refSpecs) {
|
||||
for (RefSpec r : matchingRefSpecs) {
|
||||
if (r.matchSource(branch.get())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (RefSpec r : multiMatchRefSpecs) {
|
||||
if (r.matchSource(branch.get())) {
|
||||
return true;
|
||||
}
|
||||
@@ -65,8 +78,12 @@ public class SubscribeSection {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Collection<RefSpec> getRefSpecs() {
|
||||
return Collections.unmodifiableCollection(refSpecs);
|
||||
public Collection<RefSpec> getMatchingRefSpecs() {
|
||||
return Collections.unmodifiableCollection(matchingRefSpecs);
|
||||
}
|
||||
|
||||
public Collection<RefSpec> getMultiMatchRefSpecs() {
|
||||
return Collections.unmodifiableCollection(multiMatchRefSpecs);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -74,10 +91,19 @@ public class SubscribeSection {
|
||||
StringBuilder ret = new StringBuilder();
|
||||
ret.append("[SubscribeSection, project=");
|
||||
ret.append(project);
|
||||
ret.append(", refs=[");
|
||||
for (RefSpec r : refSpecs) {
|
||||
ret.append(r.toString());
|
||||
ret.append(", ");
|
||||
if (!matchingRefSpecs.isEmpty()) {
|
||||
ret.append(", matching=[");
|
||||
for (RefSpec r : matchingRefSpecs) {
|
||||
ret.append(r.toString());
|
||||
ret.append(", ");
|
||||
}
|
||||
}
|
||||
if (!multiMatchRefSpecs.isEmpty()) {
|
||||
ret.append(", all=[");
|
||||
for (RefSpec r : multiMatchRefSpecs) {
|
||||
ret.append(r.toString());
|
||||
ret.append(", ");
|
||||
}
|
||||
}
|
||||
ret.append("]");
|
||||
return ret.toString();
|
||||
|
||||
@@ -132,7 +132,8 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
|
||||
private static final String KEY_STATE = "state";
|
||||
|
||||
private static final String SUBSCRIBE_SECTION = "allowSuperproject";
|
||||
private static final String SUBSCRIBE_REFS = "refs";
|
||||
private static final String SUBSCRIBE_MATCH_REFS = "matching";
|
||||
private static final String SUBSCRIBE_MULTI_MATCH_REFS = "all";
|
||||
|
||||
private static final String DASHBOARD = "dashboard";
|
||||
private static final String KEY_DEFAULT = "default";
|
||||
@@ -848,8 +849,12 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
|
||||
Project.NameKey p = new Project.NameKey(projectName);
|
||||
SubscribeSection ss = new SubscribeSection(p);
|
||||
for (String s : rc.getStringList(SUBSCRIBE_SECTION,
|
||||
projectName, SUBSCRIBE_REFS)) {
|
||||
ss.addRefSpec(s);
|
||||
projectName, SUBSCRIBE_MULTI_MATCH_REFS)) {
|
||||
ss.addMultiMatchRefSpec(s);
|
||||
}
|
||||
for (String s : rc.getStringList(SUBSCRIBE_SECTION,
|
||||
projectName, SUBSCRIBE_MATCH_REFS)) {
|
||||
ss.addMatchingRefSpec(s);
|
||||
}
|
||||
subscribeSections.put(p, ss);
|
||||
}
|
||||
@@ -1238,8 +1243,13 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
|
||||
private void saveSubscribeSections(Config rc) {
|
||||
for (Project.NameKey p : subscribeSections.keySet()) {
|
||||
SubscribeSection s = subscribeSections.get(p);
|
||||
for (RefSpec r : s.getRefSpecs()) {
|
||||
rc.setString(SUBSCRIBE_SECTION, p.get(), SUBSCRIBE_REFS, r.toString());
|
||||
for (RefSpec r : s.getMatchingRefSpecs()) {
|
||||
rc.setString(SUBSCRIBE_SECTION, p.get(),
|
||||
SUBSCRIBE_MATCH_REFS, r.toString());
|
||||
}
|
||||
for (RefSpec r : s.getMultiMatchRefSpecs()) {
|
||||
rc.setString(SUBSCRIBE_SECTION, p.get(),
|
||||
SUBSCRIBE_MULTI_MATCH_REFS, r.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@@ -222,33 +223,50 @@ public class SubmoduleOp {
|
||||
|
||||
private Collection<Branch.NameKey> getDestinationBranches(Branch.NameKey src,
|
||||
SubscribeSection s) throws IOException {
|
||||
Collection<Branch.NameKey> ret = new ArrayList<>();
|
||||
Collection<Branch.NameKey> ret = new HashSet<>();
|
||||
logDebug("Inspecting SubscribeSection " + s);
|
||||
for (RefSpec r : s.getRefSpecs()) {
|
||||
logDebug("Inspecting ref " + r);
|
||||
if (r.matchSource(src.get())) {
|
||||
if (r.getDestination() == null) {
|
||||
// no need to care for wildcard, as we matched already
|
||||
OpenRepo or;
|
||||
try {
|
||||
or = orm.openRepo(s.getProject(), false);
|
||||
} catch (NoSuchProjectException e) {
|
||||
// A project listed a non existent project to be allowed
|
||||
// to subscribe to it. Allow this for now.
|
||||
continue;
|
||||
}
|
||||
for (RefSpec r : s.getMatchingRefSpecs()) {
|
||||
logDebug("Inspecting [matching] ref " + r);
|
||||
if (!r.matchSource(src.get())) {
|
||||
continue;
|
||||
}
|
||||
if (r.isWildcard()) {
|
||||
// refs/heads/*[:refs/somewhere/*]
|
||||
ret.add(new Branch.NameKey(s.getProject(),
|
||||
r.expandFromSource(src.get()).getDestination()));
|
||||
} else {
|
||||
// e.g. refs/heads/master[:refs/heads/stable]
|
||||
String dest = r.getDestination();
|
||||
if (dest == null) {
|
||||
dest = r.getSource();
|
||||
}
|
||||
ret.add(new Branch.NameKey(s.getProject(), dest));
|
||||
}
|
||||
}
|
||||
|
||||
for (Ref ref : or.repo.getRefDatabase().getRefs(
|
||||
RefNames.REFS_HEADS).values()) {
|
||||
ret.add(new Branch.NameKey(s.getProject(), ref.getName()));
|
||||
}
|
||||
} else if (r.isWildcard()) {
|
||||
// refs/heads/*:refs/heads/*
|
||||
ret.add(new Branch.NameKey(s.getProject(),
|
||||
r.expandFromSource(src.get()).getDestination()));
|
||||
} else {
|
||||
// e.g. refs/heads/master:refs/heads/stable
|
||||
ret.add(new Branch.NameKey(s.getProject(), r.getDestination()));
|
||||
for (RefSpec r : s.getMultiMatchRefSpecs()) {
|
||||
logDebug("Inspecting [all] ref " + r);
|
||||
if (!r.matchSource(src.get())) {
|
||||
continue;
|
||||
}
|
||||
OpenRepo or;
|
||||
try {
|
||||
or = orm.openRepo(s.getProject(), false);
|
||||
} catch (NoSuchProjectException e) {
|
||||
// A project listed a non existent project to be allowed
|
||||
// to subscribe to it. Allow this for now, i.e. no exception is
|
||||
// thrown.
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Ref ref : or.repo.getRefDatabase().getRefs(
|
||||
RefNames.REFS_HEADS).values()) {
|
||||
if (r.getDestination() != null && !r.matchDestination(ref.getName())) {
|
||||
continue;
|
||||
}
|
||||
Branch.NameKey b = new Branch.NameKey(s.getProject(), ref.getName());
|
||||
if (!ret.contains(b)) {
|
||||
ret.add(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,10 +79,10 @@ public class Schema_120 extends SchemaVersion {
|
||||
}
|
||||
RefSpec newRefSpec = new RefSpec(subbranch.get() + ":" + superBranch.get());
|
||||
|
||||
if (!s.getRefSpecs().contains(newRefSpec)) {
|
||||
if (!s.getMatchingRefSpecs().contains(newRefSpec)) {
|
||||
// For the migration we use only exact RefSpecs, we're not trying to
|
||||
// generalize it.
|
||||
s.addRefSpec(newRefSpec);
|
||||
s.addMatchingRefSpec(newRefSpec);
|
||||
}
|
||||
|
||||
pc.commit(md);
|
||||
|
||||
Reference in New Issue
Block a user