View Javadoc
1   /*
2    * Copyright (C) 2021, Google Inc. and others
3    *
4    * This program and the accompanying materials are made available under the
5    * terms of the Eclipse Distribution License v. 1.0 which is available at
6    * https://www.eclipse.org/org/documents/edl-v10.php.
7    *
8    * SPDX-License-Identifier: BSD-3-Clause
9    */
10  package org.eclipse.jgit.gitrepo;
11  
12  import static org.eclipse.jgit.lib.Constants.DEFAULT_REMOTE_NAME;
13  import static org.eclipse.jgit.lib.Constants.R_REMOTES;
14  
15  import java.io.IOException;
16  import java.util.List;
17  
18  import org.eclipse.jgit.api.Git;
19  import org.eclipse.jgit.api.SubmoduleAddCommand;
20  import org.eclipse.jgit.api.errors.GitAPIException;
21  import org.eclipse.jgit.gitrepo.RepoCommand.ManifestErrorException;
22  import org.eclipse.jgit.gitrepo.RepoProject.CopyFile;
23  import org.eclipse.jgit.gitrepo.RepoProject.LinkFile;
24  import org.eclipse.jgit.gitrepo.internal.RepoText;
25  import org.eclipse.jgit.internal.JGitText;
26  import org.eclipse.jgit.lib.ObjectId;
27  import org.eclipse.jgit.lib.ProgressMonitor;
28  import org.eclipse.jgit.lib.Ref;
29  import org.eclipse.jgit.lib.Repository;
30  import org.eclipse.jgit.revwalk.RevCommit;
31  
32  /**
33   * Writes .gitmodules and gitlinks of parsed manifest projects into a regular
34   * repository (using git submodule commands)
35   *
36   * To write on a bare repository, use {@link BareSuperprojectWriter}
37   */
38  class RegularSuperprojectWriter {
39  
40  	private Repository repo;
41  
42  	private ProgressMonitor monitor;
43  
44  	RegularSuperprojectWriter(Repository repo, ProgressMonitor monitor) {
45  		this.repo = repo;
46  		this.monitor = monitor;
47  	}
48  
49  	RevCommit write(List<RepoProject> repoProjects)
50  			throws GitAPIException {
51  		try (Git git = new Git(repo)) {
52  			for (RepoProject proj : repoProjects) {
53  				addSubmodule(proj.getName(), proj.getUrl(), proj.getPath(),
54  						proj.getRevision(), proj.getCopyFiles(),
55  						proj.getLinkFiles(), git);
56  			}
57  			return git.commit().setMessage(RepoText.get().repoCommitMessage)
58  					.call();
59  		} catch (IOException e) {
60  			throw new ManifestErrorException(e);
61  		}
62  	}
63  
64  	private void addSubmodule(String name, String url, String path,
65  			String revision, List<CopyFile> copyfiles, List<LinkFile> linkfiles,
66  			Git git) throws GitAPIException, IOException {
67  		assert (!repo.isBare());
68  		assert (git != null);
69  		if (!linkfiles.isEmpty()) {
70  			throw new UnsupportedOperationException(
71  					JGitText.get().nonBareLinkFilesNotSupported);
72  		}
73  
74  		SubmoduleAddCommand add = git.submoduleAdd().setName(name).setPath(path)
75  				.setURI(url);
76  		if (monitor != null) {
77  			add.setProgressMonitor(monitor);
78  		}
79  
80  		Repository subRepo = add.call();
81  		if (revision != null) {
82  			try (Git sub = new Git(subRepo)) {
83  				sub.checkout().setName(findRef(revision, subRepo)).call();
84  			}
85  			subRepo.close();
86  			git.add().addFilepattern(path).call();
87  		}
88  		for (CopyFile copyfile : copyfiles) {
89  			copyfile.copy();
90  			git.add().addFilepattern(copyfile.dest).call();
91  		}
92  	}
93  
94  	private static String findRef(String ref, Repository repo)
95  			throws IOException {
96  		if (!ObjectId.isId(ref)) {
97  			Ref r = repo.exactRef(R_REMOTES + DEFAULT_REMOTE_NAME + "/" + ref); //$NON-NLS-1$
98  			if (r != null) {
99  				return r.getName();
100 			}
101 		}
102 		return ref;
103 	}
104 }