Line data Source code
1 : // Copyright (C) 2016 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.server.util.git; 16 : 17 : import com.google.gerrit.common.Nullable; 18 : import com.google.gerrit.entities.BranchNameKey; 19 : import com.google.gerrit.entities.Project; 20 : import com.google.gerrit.entities.SubmoduleSubscription; 21 : import java.net.URI; 22 : import java.net.URISyntaxException; 23 : import java.util.HashSet; 24 : import java.util.Set; 25 : import org.eclipse.jgit.lib.Config; 26 : import org.eclipse.jgit.lib.Constants; 27 : 28 : /** 29 : * It parses from a configuration file submodule sections. 30 : * 31 : * <p>Example of submodule sections: 32 : * 33 : * <pre> 34 : * [submodule "project-a"] 35 : * url = http://localhost/a 36 : * path = a 37 : * branch = . 38 : * 39 : * [submodule "project-b"] 40 : * url = http://localhost/b 41 : * path = b 42 : * branch = refs/heads/test 43 : * </pre> 44 : */ 45 : public class SubmoduleSectionParser { 46 : 47 : private final Config config; 48 : private final String canonicalWebUrl; 49 : private final BranchNameKey superProjectBranch; 50 : 51 : public SubmoduleSectionParser( 52 3 : Config config, String canonicalWebUrl, BranchNameKey superProjectBranch) { 53 3 : this.config = config; 54 3 : this.canonicalWebUrl = canonicalWebUrl; 55 3 : this.superProjectBranch = superProjectBranch; 56 3 : } 57 : 58 : public Set<SubmoduleSubscription> parseAllSections() { 59 3 : Set<SubmoduleSubscription> parsedSubscriptions = new HashSet<>(); 60 3 : for (String id : config.getSubsections("submodule")) { 61 3 : final SubmoduleSubscription subscription = parse(id); 62 3 : if (subscription != null) { 63 3 : parsedSubscriptions.add(subscription); 64 : } 65 3 : } 66 3 : return parsedSubscriptions; 67 : } 68 : 69 : @Nullable 70 : private SubmoduleSubscription parse(String id) { 71 3 : final String url = config.getString("submodule", id, "url"); 72 3 : final String path = config.getString("submodule", id, "path"); 73 3 : String branch = config.getString("submodule", id, "branch"); 74 : 75 : try { 76 3 : if (url != null 77 3 : && url.length() > 0 78 : && path != null 79 3 : && path.length() > 0 80 : && branch != null 81 3 : && branch.length() > 0) { 82 : // All required fields filled. 83 : String project; 84 : 85 3 : if (branch.equals(".")) { 86 1 : branch = superProjectBranch.branch(); 87 : } 88 : 89 : // relative URL 90 3 : if (url.startsWith("../")) { 91 : // prefix with a slash for easier relative path walks 92 2 : project = '/' + superProjectBranch.project().get(); 93 2 : String hostPart = url; 94 2 : while (hostPart.startsWith("../")) { 95 2 : int lastSlash = project.lastIndexOf('/'); 96 2 : if (lastSlash < 0) { 97 : // too many levels up, ignore for now 98 0 : return null; 99 : } 100 2 : project = project.substring(0, lastSlash); 101 2 : hostPart = hostPart.substring(3); 102 2 : } 103 2 : project = project + "/" + hostPart; 104 : 105 : // remove leading '/' 106 2 : project = project.substring(1); 107 2 : } else { 108 : // It is actually an URI. It could be ssh://localhost/project-a. 109 3 : URI targetServerURI = new URI(url); 110 3 : URI thisServerURI = new URI(canonicalWebUrl); 111 3 : String thisHost = thisServerURI.getHost(); 112 3 : String targetHost = targetServerURI.getHost(); 113 3 : if (thisHost == null || targetHost == null || !targetHost.equalsIgnoreCase(thisHost)) { 114 1 : return null; 115 : } 116 3 : String p1 = targetServerURI.getPath(); 117 3 : String p2 = thisServerURI.getPath(); 118 3 : if (!p1.startsWith(p2)) { 119 : // When we are running the server at 120 : // http://server/my-gerrit/ but the subscription is for 121 : // http://server/other-teams-gerrit/ 122 0 : return null; 123 : } 124 : // skip common part 125 3 : project = p1.substring(p2.length()); 126 : } 127 : 128 3 : while (project.startsWith("/")) { 129 2 : project = project.substring(1); 130 : } 131 : 132 3 : if (project.endsWith(Constants.DOT_GIT_EXT)) { 133 0 : project = 134 0 : project.substring( 135 : 0, // 136 0 : project.length() - Constants.DOT_GIT_EXT.length()); 137 : } 138 3 : Project.NameKey projectKey = Project.nameKey(project); 139 3 : return new SubmoduleSubscription( 140 3 : superProjectBranch, BranchNameKey.create(projectKey, branch), path); 141 : } 142 0 : } catch (URISyntaxException e) { 143 : // Error in url syntax (in fact it is uri syntax) 144 1 : } 145 1 : return null; 146 : } 147 : }