-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy pathArgsParser.groovy
More file actions
187 lines (151 loc) · 7.28 KB
/
ArgsParser.groovy
File metadata and controls
187 lines (151 loc) · 7.28 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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
package arguments
import exception.InvalidArgsException
import groovy.cli.commons.CliBuilder
import groovy.cli.commons.OptionAccessor
import org.apache.logging.log4j.Level
import java.text.ParseException
import java.text.SimpleDateFormat
class ArgsParser {
private CliBuilder cli
private OptionAccessor options
ArgsParser() {
this.cli = new CliBuilder(usage: "miningframework [options] [input] [output]",
header: "the Mining Framework take an input csv file and a name for the output dir (default: output) \n Options: ")
defParameters()
}
private defParameters() {
this.cli.h(longOpt: 'help', 'Show help for executing commands')
this.cli.r(longOpt: 'random-seed', args: 1,
argName: 'seed', 'Random seed used for shuffling merge commits array')
this.cli.s(longOpt: 'since', args: 1,
argName: 'date', 'Use commits more recent than a specific date (format YYYY-MM-DD)')
this.cli.u(longOpt: 'until', args: 1,
argName: 'date', 'Use commits older than a specific date(format YYYY-MM-DD)')
this.cli.m(longOpt: 'max-commits-per-project', args: 1,
argName: 'commits', 'Maximum number of commits to use for each project. Commits will be selected randomly, according to provided random seed')
this.cli.i(longOpt: 'injector', args: 1,
argName: 'class', 'Specify the class of the dependency injector (Must provide full name, default injectors.StaticAnalysisConflictsDetectionModule)')
this.cli.p(longOpt: 'push', args: 1, argName: 'link', 'Specify a git repository to upload the output in the end of the analysis (format https://github.com/<owner>/<name>')
this.cli.a(longOpt: 'access-key', args: 1, argName: 'access key', 'Specify the access key of the git account for when the analysis needs user access to GitHub')
this.cli.t(longOpt: 'threads', args: 1, argName: 'threads', "Number of cores used in analysis (default: 1)")
this.cli.k(longOpt: 'keep-projects', argName: 'keep projects', 'Specify that cloned projects must be kept after the analysis (those are kept in clonedRepositories/ )')
this.cli.e(longOpt: 'extension', args: 1, argName: 'file extenson', 'Specify the file extension that should be used in the analysis (e.g. .rb, .ts, .java, .cpp. Default: .java)')
this.cli.l(longOpt: 'language-separators', args: 1, argName: 'language syntactic separators', 'Specify the language separators that should be used in the analysis. Required for (and only considered when) running studies with the CSDiff tool. Default: \"{ } ( ) ; ,\"')
this.cli.log(longOpt: 'log-level', args: 1, argName: 'log level', 'Specify the minimum log level: (OFF, FATAL, ERROR, WARN, INFO, DEBUG, TRACE, ALL). Default: \"INFO\"')
this.cli.pchf(longOpt: 'project-commit-hashes-file', args: 1, argName: 'project commit hashes file', 'Path to a file with projects and commits to be analyzed')
}
Arguments parse(args) {
this.options = this.cli.parse(args)
Arguments resultArgs = new Arguments()
if (this.getArgumentQuantity() == 0 || this.options.h) {
resultArgs.setHelp()
} else {
parseInputs(resultArgs)
parseOptions(resultArgs)
}
return resultArgs
}
void printHelp() {
this.cli.usage()
}
private void parseInputs(Arguments args) {
if (this.getArgumentQuantity() > 2) {
String message = hasOptionValid() ? 'Too many arguments passed' : 'Invalid argument passed'
throw new InvalidArgsException(message)
}
String inputFile = this.options.arguments()[0]
if (!inputFile.endsWith('.csv'))
throw new InvalidArgsException('The input must be a csv file')
if (!new File(inputFile).exists())
throw new InvalidArgsException("Could not find input file: ${inputFile}")
args.setInputPath(inputFile)
if (this.getArgumentQuantity() > 1) {
String outputPath = this.options.arguments()[1]
String parsedOutputPath = outputPath.endsWith("/") ? outputPath.substring(0, outputPath.lastIndexOf("/")) : outputPath;
args.setOutputPath(parsedOutputPath)
}
}
private void parseOptions(Arguments args) {
if (this.options.r) {
args.setRandomSeed(this.options.r.toInteger())
}
if (this.options.since) {
if (!validDate(this.options.since))
throw new InvalidArgsException('Invalid since date. You must specify it with the format YYYY-MM-DD')
args.setSinceDate(this.options.since)
}
if (this.options.until) {
if (!validDate(this.options.until))
throw new InvalidArgsException('Invalid until date. You must specify it with the format YYYY-MM-DD')
args.setUntilDate(this.options.until)
}
if (this.options.m) {
args.setMaxCommitsPerProject(this.options.m.toInteger())
}
if (this.options.injector) {
try {
args.setInjector(Class.forName(this.options.injector));
} catch (Exception e) {
throw new InvalidArgsException('Invalid injector class. be sure it is in your classpath')
}
}
if (this.options.push) {
if (!repositoryExists(this.options.push))
throw new InvalidArgsException('Inexistent remote git repository.')
args.setResultsRemoteRepositoryURL(this.options.push)
}
if (this.options.a) {
args.setAccessKey(this.options.a)
}
if (this.options.t) {
args.setNumOfThreads(this.options.t.toInteger())
}
if (this.options.k) {
args.setKeepProjects()
}
if(this.options.extension) {
args.setFileExtension(this.options.extension)
}
if(this.options.l) {
args.setLanguageSyntacticSeparators(this.options.l)
}
if(this.options.log) {
args.setLogLevel(Level.toLevel(this.options.log))
}
if (this.options.pchf) {
args.setProjectCommitHashesFile(this.options.pchf)
}
}
private boolean repositoryExists(String repositoryURL) {
try {
final URL url = new URL(repositoryURL)
HttpURLConnection huc = (HttpURLConnection) url.openConnection()
huc.setRequestMethod("HEAD")
return huc.getResponseCode() == 200
} catch (MalformedURLException e) {
throw new InvalidArgsException('Invalid url.')
}
}
private boolean validDate(String value) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-dd")
try {
format.setLenient(false)
format.parse(value)
return true;
} catch (ParseException | NullPointerException e) {
return false;
}
}
private boolean hasOptionValid() {
List<String> arguments = this.options.arguments()
for (String arg : arguments) {
if (arg.contains('-') || arg.contains('--')) {
return false
}
}
return true
}
private int getArgumentQuantity() {
return this.options.arguments().size()
}
}