diff --git a/README.md b/README.md
index 826ba90910..47b6943e09 100644
--- a/README.md
+++ b/README.md
@@ -15,6 +15,10 @@ RepoSense is a contribution analysis tool for Git repositories. It is particular
- [User Guide for the latest `master` (not yet released to users)](https://reposense.github.io/RepoSense)
---
+### Our Contributors :
+
+
+
**Acknowledgements**: The web previews of RepoSense is powered by Netlify and Surge.
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 56afac2e4f..97789ce3b0 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -7574,9 +7574,9 @@
"dev": true
},
"node_modules/follow-redirects": {
- "version": "1.15.2",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
- "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
+ "version": "1.15.4",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
+ "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==",
"dev": true,
"funding": [
{
@@ -22394,9 +22394,9 @@
"dev": true
},
"follow-redirects": {
- "version": "1.15.2",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
- "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
+ "version": "1.15.4",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
+ "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==",
"dev": true
},
"for-each": {
diff --git a/src/main/java/reposense/parser/ArgsParser.java b/src/main/java/reposense/parser/ArgsParser.java
index 05632bfb4d..91a46c180f 100644
--- a/src/main/java/reposense/parser/ArgsParser.java
+++ b/src/main/java/reposense/parser/ArgsParser.java
@@ -80,6 +80,10 @@ public class ArgsParser {
private static final String MESSAGE_INVALID_CONFIG_JSON = "%s Ignoring the report config provided.";
private static final String MESSAGE_SINCE_D1_WITH_PERIOD = "You may be using --since d1 with the --period flag. "
+ "This may result in an incorrect date range being analysed.";
+ private static final String MESSAGE_SINCE_DATE_LATER_THAN_UNTIL_DATE =
+ "\"Since Date\" cannot be later than \"Until Date\".";
+ private static final String MESSAGE_SINCE_DATE_LATER_THAN_TODAY_DATE =
+ "\"Since Date\" must not be later than today's date.";
private static final Path EMPTY_PATH = Paths.get("");
private static final Path DEFAULT_CONFIG_PATH = Paths.get(System.getProperty("user.dir")
+ File.separator + "config" + File.separator);
@@ -258,76 +262,78 @@ private static ArgumentParser getArgumentParser() {
* @throws ParseException if the given string arguments fails to parse to a {@link CliArguments} object.
*/
public static CliArguments parse(String[] args) throws HelpScreenException, ParseException {
+ ArgumentParser parser = getArgumentParser();
+ Namespace results;
+
try {
- ArgumentParser parser = getArgumentParser();
- Namespace results = parser.parseArgs(args);
-
- Path configFolderPath = results.get(CONFIG_FLAGS[0]);
- Path reportFolderPath = results.get(VIEW_FLAGS[0]);
- Path outputFolderPath = results.get(OUTPUT_FLAGS[0]);
- ZoneId zoneId = results.get(TIMEZONE_FLAGS[0]);
- Path assetsFolderPath = results.get(ASSETS_FLAGS[0]);
- List locations = results.get(REPO_FLAGS[0]);
- List formats = FileType.convertFormatStringsToFileTypes(results.get(FORMAT_FLAGS[0]));
- boolean isStandaloneConfigIgnored = results.get(IGNORE_CONFIG_FLAGS[0]);
- boolean isFileSizeLimitIgnored = results.get(IGNORE_SIZELIMIT_FLAGS[0]);
- boolean shouldIncludeLastModifiedDate = results.get(LAST_MODIFIED_DATE_FLAGS[0]);
- boolean shouldPerformShallowCloning = results.get(SHALLOW_CLONING_FLAGS[0]);
- boolean shouldFindPreviousAuthors = results.get(FIND_PREVIOUS_AUTHORS_FLAGS[0]);
- boolean isTestMode = results.get(TEST_MODE_FLAG[0]);
- int numCloningThreads = results.get(CLONING_THREADS_FLAG[0]);
- int numAnalysisThreads = results.get(ANALYSIS_THREADS_FLAG[0]);
-
- CliArguments.Builder cliArgumentsBuilder = new CliArguments.Builder()
- .configFolderPath(configFolderPath)
- .reportDirectoryPath(reportFolderPath)
- .outputFilePath(outputFolderPath)
- .zoneId(zoneId)
- .assetsFilePath(assetsFolderPath)
- .locations(locations)
- .formats(formats)
- .isStandaloneConfigIgnored(isStandaloneConfigIgnored)
- .isFileSizeLimitIgnored(isFileSizeLimitIgnored)
- .isLastModifiedDateIncluded(shouldIncludeLastModifiedDate)
- .isShallowCloningPerformed(shouldPerformShallowCloning)
- .isFindingPreviousAuthorsPerformed(shouldFindPreviousAuthors)
- .numCloningThreads(numCloningThreads)
- .numAnalysisThreads(numAnalysisThreads)
- .isTestMode(isTestMode);
-
- LogsManager.setLogFolderLocation(outputFolderPath);
-
- if (locations == null && configFolderPath.equals(DEFAULT_CONFIG_PATH)) {
- logger.info(MESSAGE_USING_DEFAULT_CONFIG_PATH);
- }
+ results = parser.parseArgs(args);
+ } catch (HelpScreenException hse) {
+ throw hse;
+ } catch (ArgumentParserException ape) {
+ throw new ParseException(getArgumentParser().formatUsage() + ape.getMessage() + "\n");
+ }
+
+ Path configFolderPath = results.get(CONFIG_FLAGS[0]);
+ Path reportFolderPath = results.get(VIEW_FLAGS[0]);
+ Path outputFolderPath = results.get(OUTPUT_FLAGS[0]);
+ ZoneId zoneId = results.get(TIMEZONE_FLAGS[0]);
+ Path assetsFolderPath = results.get(ASSETS_FLAGS[0]);
+ List locations = results.get(REPO_FLAGS[0]);
+ List formats = FileType.convertFormatStringsToFileTypes(results.get(FORMAT_FLAGS[0]));
+ boolean isStandaloneConfigIgnored = results.get(IGNORE_CONFIG_FLAGS[0]);
+ boolean isFileSizeLimitIgnored = results.get(IGNORE_SIZELIMIT_FLAGS[0]);
+ boolean shouldIncludeLastModifiedDate = results.get(LAST_MODIFIED_DATE_FLAGS[0]);
+ boolean shouldPerformShallowCloning = results.get(SHALLOW_CLONING_FLAGS[0]);
+ boolean shouldFindPreviousAuthors = results.get(FIND_PREVIOUS_AUTHORS_FLAGS[0]);
+ boolean isTestMode = results.get(TEST_MODE_FLAG[0]);
+ int numCloningThreads = results.get(CLONING_THREADS_FLAG[0]);
+ int numAnalysisThreads = results.get(ANALYSIS_THREADS_FLAG[0]);
+
+ CliArguments.Builder cliArgumentsBuilder = new CliArguments.Builder()
+ .configFolderPath(configFolderPath)
+ .reportDirectoryPath(reportFolderPath)
+ .outputFilePath(outputFolderPath)
+ .zoneId(zoneId)
+ .assetsFilePath(assetsFolderPath)
+ .locations(locations)
+ .formats(formats)
+ .isStandaloneConfigIgnored(isStandaloneConfigIgnored)
+ .isFileSizeLimitIgnored(isFileSizeLimitIgnored)
+ .isLastModifiedDateIncluded(shouldIncludeLastModifiedDate)
+ .isShallowCloningPerformed(shouldPerformShallowCloning)
+ .isFindingPreviousAuthorsPerformed(shouldFindPreviousAuthors)
+ .numCloningThreads(numCloningThreads)
+ .numAnalysisThreads(numAnalysisThreads)
+ .isTestMode(isTestMode);
+
+ LogsManager.setLogFolderLocation(outputFolderPath);
+
+ if (locations == null && configFolderPath.equals(DEFAULT_CONFIG_PATH)) {
+ logger.info(MESSAGE_USING_DEFAULT_CONFIG_PATH);
+ }
- addReportConfigToBuilder(cliArgumentsBuilder, results);
- addAnalysisDatesToBuilder(cliArgumentsBuilder, results);
+ addReportConfigToBuilder(cliArgumentsBuilder, results);
+ addAnalysisDatesToBuilder(cliArgumentsBuilder, results);
- boolean isViewModeOnly = reportFolderPath != null
- && !reportFolderPath.equals(EMPTY_PATH)
- && configFolderPath.equals(DEFAULT_CONFIG_PATH)
- && locations == null;
- cliArgumentsBuilder.isViewModeOnly(isViewModeOnly);
+ boolean isViewModeOnly = reportFolderPath != null
+ && !reportFolderPath.equals(EMPTY_PATH)
+ && configFolderPath.equals(DEFAULT_CONFIG_PATH)
+ && locations == null;
+ cliArgumentsBuilder.isViewModeOnly(isViewModeOnly);
- boolean isAutomaticallyLaunching = reportFolderPath != null;
- if (isAutomaticallyLaunching && !reportFolderPath.equals(EMPTY_PATH) && !isViewModeOnly) {
- logger.info(String.format("Ignoring argument '%s' for --view.", reportFolderPath.toString()));
- }
- cliArgumentsBuilder.isAutomaticallyLaunching(isAutomaticallyLaunching);
+ boolean isAutomaticallyLaunching = reportFolderPath != null;
+ if (isAutomaticallyLaunching && !reportFolderPath.equals(EMPTY_PATH) && !isViewModeOnly) {
+ logger.info(String.format("Ignoring argument '%s' for --view.", reportFolderPath.toString()));
+ }
+ cliArgumentsBuilder.isAutomaticallyLaunching(isAutomaticallyLaunching);
- boolean shouldPerformFreshCloning = isTestMode
- ? results.get(FRESH_CLONING_FLAG[0])
- : DEFAULT_SHOULD_FRESH_CLONE;
- cliArgumentsBuilder.isFreshClonePerformed(shouldPerformFreshCloning);
+ boolean shouldPerformFreshCloning = isTestMode
+ ? results.get(FRESH_CLONING_FLAG[0])
+ : DEFAULT_SHOULD_FRESH_CLONE;
+ cliArgumentsBuilder.isFreshClonePerformed(shouldPerformFreshCloning);
- return cliArgumentsBuilder.build();
- } catch (HelpScreenException hse) {
- throw hse;
- } catch (ArgumentParserException ape) {
- throw new ParseException(getArgumentParser().formatUsage() + ape.getMessage() + "\n");
- }
+ return cliArgumentsBuilder.build();
}
/**
@@ -420,8 +426,13 @@ private static void addAnalysisDatesToBuilder(CliArguments.Builder builder, Name
? untilDate
: currentDate;
- TimeUtil.verifySinceDateIsValid(sinceDate, currentDate);
- TimeUtil.verifyDatesRangeIsCorrect(sinceDate, untilDate);
+ if (sinceDate.compareTo(currentDate) > 0) {
+ throw new ParseException(MESSAGE_SINCE_DATE_LATER_THAN_TODAY_DATE);
+ }
+
+ if (sinceDate.compareTo(untilDate) > 0) {
+ throw new ParseException(MESSAGE_SINCE_DATE_LATER_THAN_UNTIL_DATE);
+ }
builder.sinceDate(sinceDate)
.isSinceDateProvided(isSinceDateProvided)
diff --git a/src/main/java/reposense/parser/RepoConfigCsvParser.java b/src/main/java/reposense/parser/RepoConfigCsvParser.java
index 8c22be4a57..4a084d31a9 100644
--- a/src/main/java/reposense/parser/RepoConfigCsvParser.java
+++ b/src/main/java/reposense/parser/RepoConfigCsvParser.java
@@ -115,20 +115,19 @@ protected void processLine(List results, CSVRecord record) th
// If file diff limit is specified
if (fileSizeLimitStringList.size() > 0) {
+ String fileSizeLimitString = fileSizeLimitStringList.get(0).trim();
+ int parseValue;
+
if (isFileSizeLimitIgnored) {
logger.warning("Ignoring file size limit column since file size limit is ignored");
isFileSizeLimitOverriding = false;
+ } else if (!StringsUtil.isNumeric(fileSizeLimitString)
+ || (parseValue = Integer.parseInt(fileSizeLimitString)) <= 0) {
+ logger.warning(String.format("Values in \"%s\" column should be positive integers.",
+ FILESIZE_LIMIT_HEADER[0]));
+ isFileSizeLimitOverriding = false;
} else {
- String fileSizeLimitString = fileSizeLimitStringList.get(0).trim();
- int parseValue;
- if (!StringsUtil.isNumeric(fileSizeLimitString)
- || (parseValue = Integer.parseInt(fileSizeLimitString)) <= 0) {
- logger.warning(String.format("Values in \"%s\" column should be positive integers.",
- FILESIZE_LIMIT_HEADER[0]));
- isFileSizeLimitOverriding = false;
- } else {
- fileSizeLimit = parseValue;
- }
+ fileSizeLimit = parseValue;
}
}
diff --git a/src/main/java/reposense/util/TimeUtil.java b/src/main/java/reposense/util/TimeUtil.java
index 96a71b7e17..83de42414c 100644
--- a/src/main/java/reposense/util/TimeUtil.java
+++ b/src/main/java/reposense/util/TimeUtil.java
@@ -9,7 +9,6 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import reposense.parser.ParseException;
import reposense.parser.SinceDateArgumentType;
import reposense.system.LogsManager;
@@ -23,10 +22,6 @@ public class TimeUtil {
// "uuuu" is used for year since "yyyy" does not work with ResolverStyle.STRICT
private static final DateTimeFormatter CLI_ARGS_DATE_FORMAT = DateTimeFormatter.ofPattern("d/M/uuuu HH:mm:ss");
- private static final String MESSAGE_SINCE_DATE_LATER_THAN_UNTIL_DATE =
- "\"Since Date\" cannot be later than \"Until Date\".";
- private static final String MESSAGE_SINCE_DATE_LATER_THAN_TODAY_DATE =
- "\"Since Date\" must not be later than today's date.";
private static final String EARLIEST_VALID_DATE = "1970-01-01T00:00:00";
private static final String LATEST_VALID_DATE = "2099-12-31T23:59:59";
@@ -168,30 +163,6 @@ public static boolean isEqualToArbitraryFirstDateConverted(LocalDateTime dateTim
return dateTime.equals(getArbitraryFirstCommitDateConverted(zoneId));
}
- /**
- * Verifies that {@code sinceDate} is earlier than {@code untilDate}.
- *
- * @throws ParseException if {@code sinceDate} supplied is later than {@code untilDate}.
- */
- public static void verifyDatesRangeIsCorrect(LocalDateTime sinceDate, LocalDateTime untilDate)
- throws ParseException {
- if (sinceDate.compareTo(untilDate) > 0) {
- throw new ParseException(MESSAGE_SINCE_DATE_LATER_THAN_UNTIL_DATE);
- }
- }
-
- /**
- * Verifies that {@code sinceDate} is no later than the date of report generation, given by {@code currentDate}.
- *
- * @throws ParseException if {@code sinceDate} supplied is later than date of report generation.
- */
- public static void verifySinceDateIsValid(LocalDateTime sinceDate, LocalDateTime currentDate)
- throws ParseException {
- if (sinceDate.compareTo(currentDate) > 0) {
- throw new ParseException(MESSAGE_SINCE_DATE_LATER_THAN_TODAY_DATE);
- }
- }
-
/**
* Extracts the first substring of {@code date} string that matches the {@code DATE_FORMAT_REGEX}.
*/
diff --git a/src/test/java/reposense/parser/ArgsParserTest.java b/src/test/java/reposense/parser/ArgsParserTest.java
index 11fa3a5714..1ed90dbbc9 100644
--- a/src/test/java/reposense/parser/ArgsParserTest.java
+++ b/src/test/java/reposense/parser/ArgsParserTest.java
@@ -11,6 +11,7 @@
import java.time.LocalDateTime;
import java.time.Month;
import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
@@ -606,6 +607,36 @@ public void sinceDate_laterThanUntilDate_throwsParseException() {
Assertions.assertThrows(ParseException.class, () -> ArgsParser.parse(translateCommandline(input)));
}
+ @Test
+ public void sinceDate_laterThanCurrentDate_throwsParseException() {
+ LocalDateTime tomorrowDateTime = LocalDateTime.now()
+ .plusDays(1L);
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
+ String tomorrow = tomorrowDateTime.format(formatter);
+
+
+ String input = DEFAULT_INPUT_BUILDER.addSinceDate(tomorrow)
+ .build();
+ Assertions.assertThrows(ParseException.class, () -> ArgsParser.parse(translateCommandline(input)));
+ }
+
+ @Test
+ public void sinceDate_beforeUntilDateAndLaterThanCurrentDate_throwsParseException() {
+ LocalDateTime tomorrowDateTime = LocalDateTime.now()
+ .plusDays(1L);
+ LocalDateTime dayAfterDateTime = LocalDateTime.now()
+ .plusDays(2L);
+
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
+ String tomorrow = tomorrowDateTime.format(formatter);
+ String dayAfter = dayAfterDateTime.format(formatter);
+
+ String input = DEFAULT_INPUT_BUILDER.addSinceDate(tomorrow)
+ .addUntilDate(dayAfter)
+ .build();
+ Assertions.assertThrows(ParseException.class, () -> ArgsParser.parse(translateCommandline(input)));
+ }
+
@Test
public void period_withBothSinceDateAndUntilDate_throwsParseException() {
String input = DEFAULT_INPUT_BUILDER.addPeriod("18d")