forked from reposense/RepoSense
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGitClone.java
More file actions
122 lines (110 loc) · 5.37 KB
/
GitClone.java
File metadata and controls
122 lines (110 loc) · 5.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package reposense.git;
import static reposense.system.CommandRunner.runCommand;
import static reposense.util.StringsUtil.addQuote;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.logging.Level;
import java.util.logging.Logger;
import reposense.git.exception.GitBranchException;
import reposense.git.exception.GitCloneException;
import reposense.model.RepoConfiguration;
import reposense.system.CommandRunner;
import reposense.system.CommandRunnerProcess;
import reposense.system.LogsManager;
import reposense.util.FileUtil;
/**
* Contains git clone related functionalities.
* Git clone is responsible for cloning a local/remote repository into a new directory.
*/
public class GitClone {
private static final Logger logger = LogsManager.getLogger(GitClone.class);
/**
* Runs "git clone --bare" command asynchronously to clone a bare repo specified in the {@code config}
* into the folder {@code outputFolderName}.
*
* @return an instance of {@code CommandRunnerProcess} to allow tracking the status of the cloning process.
* @throws GitCloneException when an error occurs during command execution.
*/
public static CommandRunnerProcess cloneBareAsync(RepoConfiguration config, Path rootPath,
String outputFolderName) throws GitCloneException {
try {
return CommandRunner.runCommandAsync(rootPath, getCloneBareCommand(config, outputFolderName));
} catch (RuntimeException rte) {
throw new GitCloneException(rte);
}
}
/**
* Clones repo specified in the {@code config} and updates it with the branch info.
*/
public static void clone(RepoConfiguration config) throws GitCloneException {
try {
FileUtil.deleteDirectory(config.getRepoRoot());
logger.info("Cloning from " + config.getLocation() + "...");
Path rootPath = Paths.get(FileUtil.REPOS_ADDRESS, config.getRepoFolderName());
Files.createDirectories(rootPath);
String command = String.format("git clone %s %s", addQuote(config.getLocation().toString()),
config.getRepoName());
runCommand(rootPath, command);
logger.info("Cloning completed!");
} catch (RuntimeException rte) {
logger.log(Level.SEVERE, "Error encountered in Git Cloning, will attempt to continue analyzing", rte);
throw new GitCloneException(rte);
//Due to an unsolved bug on Windows Git, for some repository, Git Clone will return an error even
// though the repo is cloned properly.
} catch (IOException ioe) {
throw new GitCloneException(ioe);
}
try {
config.updateBranch();
GitCheckout.checkout(config.getRepoRoot(), config.getBranch());
} catch (GitBranchException gbe) {
logger.log(Level.SEVERE,
"Exception met while trying to get current branch of repo. Analysis terminated.", gbe);
throw new GitCloneException(gbe);
} catch (RuntimeException rte) {
logger.log(Level.SEVERE, "Branch does not exist! Analysis terminated.", rte);
throw new GitCloneException(rte);
}
}
/**
* Clones a bare repo specified in {@code config} into the folder {@code outputFolderName}.
* @throws IOException if it fails to delete a directory.
*/
public static void cloneBare(RepoConfiguration config, String outputFolderName) throws IOException {
Path rootPath = Paths.get(FileUtil.REPOS_ADDRESS, config.getRepoFolderName());
FileUtil.deleteDirectory(Paths.get(rootPath.toString(), outputFolderName).toString());
Files.createDirectories(rootPath);
String command = getCloneBareCommand(config, outputFolderName);
runCommand(rootPath, command);
}
/**
* Performs a full clone from {@code clonedBareRepoLocation} into the folder {@code outputFolderName} and
* directly branches out to {@code targetBranch}.
* @throws IOException if it fails to delete a directory.
* @throws GitCloneException when an error occurs during command execution.
*/
public static void cloneFromBareAndUpdateBranch(Path rootPath, RepoConfiguration config)
throws GitCloneException, IOException {
Path relativePath = rootPath.relativize(FileUtil.getBareRepoPath(config));
String outputFolderName = Paths.get(config.getRepoFolderName(), config.getRepoName()).toString();
FileUtil.deleteDirectory(Paths.get(FileUtil.REPOS_ADDRESS, outputFolderName).toString());
String command = String.format(
"git clone %s --branch %s %s", relativePath, config.getBranch(), outputFolderName);
try {
runCommand(rootPath, command);
} catch (RuntimeException rte) {
logger.severe("Exception met while cloning or checking out " + config.getDisplayName() + "."
+ "Analysis terminated.");
throw new GitCloneException(rte);
}
}
/**
* Constructs the command to clone a bare repo specified in the {@code config}
* into the folder {@code outputFolderName}.
*/
private static String getCloneBareCommand(RepoConfiguration config, String outputFolderName) {
return "git clone --bare " + config.getLocation() + " " + outputFolderName;
}
}