diff --git a/.gitignore b/.gitignore index 451cddfe4d..73a3abf12e 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ *.tmp ft_temp/ +rc_temp/ /target/ .gradle/ build/ diff --git a/config/report-config.yaml b/config/report-config.yaml new file mode 100644 index 0000000000..a530aa7a91 --- /dev/null +++ b/config/report-config.yaml @@ -0,0 +1 @@ +title: RepoSense Report diff --git a/docs/_markbind/layouts/ug-sitenav.md b/docs/_markbind/layouts/ug-sitenav.md index 489edfb0b1..43c7e62a00 100644 --- a/docs/_markbind/layouts/ug-sitenav.md +++ b/docs/_markbind/layouts/ug-sitenav.md @@ -6,6 +6,7 @@ {name: "Sharing reports", link: "ug/sharingReports.html"}, {name: "Appendices"}, {level: 2, name: "CLI syntax reference", link: "ug/cli.html"}, + {level: 2, name: "Getting started with `report-config.yaml`", link: "ug/reportConfig.html"}, {level: 2, name: "Config files format", link: "ug/configFiles.html"}, {level: 2, name: "Advanced syntax: `author-config.csv`", link: "ug/authorConfigSyntax.html"}, {level: 2, name: "Using `@@author` tags", link: "ug/usingAuthorTags.html"}, diff --git a/docs/dg/cli.md b/docs/dg/cli.md index db708f46c4..e642e15f20 100644 --- a/docs/dg/cli.md +++ b/docs/dg/cli.md @@ -17,7 +17,7 @@ syntax reference under Appendix section of User Guide. -* Used in `ConfigSystemTest`. +* Used in `ConfigSystemTest` and `ReportConfigSystemTest`. * Some test cases performs shallow cloning while some does not. Fresh cloning ensures that the test cases that does not perform shallow cloning will clone the repo again if the previous test case uses shallow cloning, ensuring correctness of the analysis. diff --git a/docs/images/report-config-report.png b/docs/images/report-config-report.png new file mode 100644 index 0000000000..dba37fb224 Binary files /dev/null and b/docs/images/report-config-report.png differ diff --git a/docs/ug/cli.md b/docs/ug/cli.md index e524282382..006608a182 100644 --- a/docs/ug/cli.md +++ b/docs/ug/cli.md @@ -68,7 +68,7 @@ partial credit.
**`--config CONFIG_DIRECTORY`**: Specifies that config files located in `CONFIG_DIRECTORY` should be used to customize the report. -* Parameter: `CONFIG_DIRECTORY` The directory containing the config files. Should contain a `repo-config.csv` file. Optionally, can contain an `author-config.csv` file or/and a `group-config.csv` file or/and a `report-config.json` file or/and a `blurbs.md` file. +* Parameter: `CONFIG_DIRECTORY` The directory containing the config files. Should contain a `repo-config.csv` file or/and a `report-config.yaml` file. Optionally, can contain an `author-config.csv` file or/and a `group-config.csv` file or/and a `blurbs.md` file. * Alias: `-c` * Example: `java -jar RepoSense.jar --config ./config` @@ -76,6 +76,7 @@ partial credit. * Cannot be used with `--repos`. The `--repos` flag will take precedence over this flag. * If both `--repos` and `--config` are not specified, RepoSense looks for config files in the `./config` directory. +* If both `repo-config.csv` and `report-config.yaml` are present in the config file, `report-config.yaml` will take precedence over **all CSV files** as long as the `repos` field is correctly formatted. * Config files must follow [this](./configFiles.html) format.
@@ -253,6 +254,8 @@ Cannot be used with `--last-modified-date`. This may result in an incorrect last ### `--since`, `-s` +
+ **`--since START_DATE`**: Specifies the start date for the period to be analyzed. * Parameter: `START_DATE` The first day of the period to be analyzed (with optional time specification), in one of the following formats:
``` @@ -272,6 +275,7 @@ Cannot be used with `--last-modified-date`. This may result in an incorrect last * If `d1` is specified as the start date (`--since d1` or `-s d1`), then the program will search for the earliest commit date of all repositories and use that as the start date. * If `d1` is specified together with `--period`, then the program will warn that the date range being analyzed may be incorrect. +
@@ -301,6 +305,8 @@ Cannot be used with `--last-modified-date`. This may result in an incorrect last ### `--until`, `-u` +
+ **`--until END_DATE`**: Specifies the end date of the analysis period. * Parameter: `END_DATE` The last date of the period to be analyzed (with optional time specification), in one of the following formats:
``` @@ -318,6 +324,7 @@ Default: Note: If the end date is not specified, the date of generating the report will be taken as the end date. +
diff --git a/docs/ug/configFiles.md b/docs/ug/configFiles.md index 70c6763ea1..a701c40e3c 100644 --- a/docs/ug/configFiles.md +++ b/docs/ug/configFiles.md @@ -46,7 +46,7 @@ Given below are the details of the various config files used by RepoSense. | Ignore File Size Limit | Enter **`yes`** to ignore both the default file size limit and the file size limit possibly set by the user in `repo-config.csv`. | | Skip Ignored File Analysis | Enter **`yes`** to ignore analysis of files exceeding the file size limit entirely. If file analysis is skipped, all information about the file will be omitted from the generated report. This option can significantly improve report generation time. | | Since Date | Enter since date in the format of `yyyy/mm/dd` to signify the start date of analysis. If the field is ignored, the date will be set to the default one or the date indicated in CLI flags | -| Until Date | Enter since date in the format of `yyyy/mm/dd` to signify the end date of analysis. If the field is ignored, the date will be set to the default one or the date indicated in CLI flags | +| Until Date | Enter until date in the format of `yyyy/mm/dd` to signify the end date of analysis. If the field is ignored, the date will be set to the default one or the date indicated in CLI flags | The Shallow Cloning option is incompatible with the "--last-modified-date" CLI flag. @@ -98,11 +98,11 @@ If `author-config.csv` is not given and the repo has not provided author details Optionally, you can provide a `group-config.csv`(which should be in the same directory as `repo-config.csv` file) to provide details on any custom groupings for files in specified repositories ([example](group-config.csv)). It should contain the following columns: -| Column Name | Explanation | -|-------------|-------------| -| Repository's Location | Same as `repo-config.csv`. Default: all the repos in `repo-config.csv` | -| Group Name {{ mandatory }} | Name of the group, e.g.,`test`. | -| Globs * {{ mandatory }} | The list of file path globs to include for specified group, e.g.,`**/test/*;**.java`. | +| Column Name | Explanation | +|----------------------------|---------------------------------------------------------------------------------------| +| Repository's Location | Same as `repo-config.csv`. Default: all the repos in `repo-config.csv` | +| Group Name {{ mandatory }} | Name of the group, e.g.,`test`. | +| Globs * {{ mandatory }} | The list of file path globs to include for specified group, e.g.,`**/test/*;**.java`. | * **Multi-value column**: multiple values can be entered in this column using a semicolon `;` as the separator. @@ -111,12 +111,12 @@ e.g.: `example.java` in `example-repo` can either be in the `test` group or the -## `report-config.json` +## `report-config.yaml` -You can optionally use `report-config.json` to customize report generation by providing the following information. ([example](report-config.json)) +You can also optionally use a `report-config.yaml` file to quickly define the repository information for the repositories you are interested in tracking and generating your very own code portfolio. +The configurations of this file will override the CSV files if the `repos` field of the file is present and correctly formatted. -**Fields to provide**: -* `title`: Title of the generated report, which is also the title of the deployed dashboard. Default: "RepoSense Report" +Please refer to this [guide](./reportConfig.html#advanced-report-configuration). diff --git a/docs/ug/customizingReports.md b/docs/ug/customizingReports.md index 92c2bbc4b7..188dc478fd 100644 --- a/docs/ug/customizingReports.md +++ b/docs/ug/customizingReports.md @@ -15,6 +15,21 @@ The report can be customized using several ways, as explained below. +### Configuration Options Overview + +RepoSense offers multiple ways to customize your reports, with varying levels of complexity and flexibility: + +1. **CLI flags** - The simplest, most direct approach for basic customization +2. **report-config.yaml** - A user-friendly single file for typical use cases +3. **CSV config files** - A more powerful option with granular control for advanced scenarios + +When deciding which configuration method to use: +- **CLI flags** are ideal for quick, one-off reports with minimal customization. +- **report-config.yaml** is recommended for most users as it provides a good balance of usability and features in a single file. +- **CSV config files** offer the most flexibility for complex scenarios, such as managing large teams or requiring fine-grained control. + + + ### Customize using CLI flags **The simplest approach is to provide additional flags when running RepoSense.** The various flags are given in the panel below. @@ -23,9 +38,20 @@ The report can be customized using several ways, as explained below. +### Customize using report-config.yaml + +**The `report-config.yaml` file provides a more user-friendly way for users to customize their reports in more detail compared to the CLI flags.** + +Please refer to this [page](./reportConfig.html) to get started. + +Note that configurations in `report-config.yaml` will override the configurations in the CSV config files when both are present. + + ### Customize using CSV config files -**Another, more powerful, way to customize the report is by using dedicated config files.** In this case you need to use the `--config` flag instead of the `--repo` flag when running RepoSense, as follows: +**Another, more powerful, way to customize the report is by using dedicated config files.** You can refer to this [section](./configFiles.html) to find out more about the CSV file formats. + +In this case you need to use the `--config` flag instead of the `--repo` flag when running RepoSense, as follows: {{ embed("Appendix: **CLI syntax reference → `config` flag**", "cli.md#section-config") }} diff --git a/docs/ug/report-config.json b/docs/ug/report-config.json deleted file mode 100644 index 8165c98ac4..0000000000 --- a/docs/ug/report-config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "title": "CS2103 RepoSense Report" -} diff --git a/docs/ug/reportConfig.md b/docs/ug/reportConfig.md new file mode 100644 index 0000000000..7a50b86537 --- /dev/null +++ b/docs/ug/reportConfig.md @@ -0,0 +1,249 @@ +{% set title = "Appendix: Getting started with `report-config.yaml`" %} + +title: "{{ title | safe }}" +pageNav: 3 + + +{% set mandatory %}mandatory{% endset %} +{% from 'scripts/macros.njk' import embed, step with context %} + +

{{ title }}

+ +RepoSense allows you to easily showcase your coding portfolio by generating visualization reports of your contributions across different repositories. +This guide will help you set up your first RepoSense report using the `report-config.yaml` file. + +## What is `report-config.yaml`? + +The `report-config.yaml` file is a simple configuration file that lets you define which repositories you want to include in your RepoSense report in more detail compared to the CLI flags. +It's designed to be user-friendly, especially for beginners who want to quickly set up a code portfolio without dealing with complex configurations. + +For more sophisticated use cases that require additional flexibility, +RepoSense's [CSV configuration files](./customizingReports.html#customize-using-csv-config-files) offer an alternative configuration approach with expanded capabilities. + +## Quick Start Guide + +### Step 1: Create a `report-config.yaml` file + +Create a new file named `report-config.yaml` in your project directory with the following basic structure: + +```yaml +title: "Your Portfolio Title" +repos: + - repo: "https://github.com/repo/yourrepo.git" + branches: + - branch: main + blurb: "Short description of this project" + authors: + - author-git-host-id: Your username on GitHub, GitLab or Bitbucket + author-display-name: Your display name + author-git-author-name: Author Name Of Your Git Configuration + author-emails: + - emails-of-your-commits@email.com + - emails-of-your-git-configuration@email.com +``` + + + +The `author-display-name`, `author-git-author-name` and `author-emails` fields are optional. + +However, users are encouraged to add their Git author name `author-git-author-name` and emails `author-emails` in their Git configuration related to their commits so that +the commits can be successfully captured. + + +### Step 2: Add your repositories + +You can add multiple repositories to showcase different projects. Here's an example: + +```yaml +title: "John Doe's Code Portfolio" +repos: + - repo: https://github.com/john/ip.git + branches: + - branch: master + blurb: "Individual Project - Task Manager Application" + authors: + - author-git-host-id: johnDoe + author-display-name: John Doe + + - repo: https://github.com/john/tp.git + branches: + - branch: master + blurb: "Team Project - Event Management System" + authors: + - author-git-host-id: johnDoe + author-display-name: John Doe +``` + +### Step 3: Generate your report + +To run RepoSense with `report-config.yaml`: + +1. Create a `config` folder in the same directory as the RepoSense.jar file. +2. Add your `report-config.yaml` to the `config` folder. +3. Run the command:`java -jar RepoSense.jar` + + + +Please note that the above command will only analyse your commits one month before the current date. If you would like to +specify the period for report generation, you can use the `--since` and `--until` flags. + +`java -jar RepoSense.jar --since START_DATE --until END_DATE` + +{{ embed("Appendix: **CLI syntax reference → `since` flag**", "cli.md#section-since-date") }} +{{ embed("Appendix: **CLI syntax reference → `until` flag**", "cli.md#section-until-date") }} + + + + + +Additionally, you can add a `--portfolio` flag to generate a more optimized view of your report. + + +That's it! RepoSense will analyze the repositories you specified and generate a report that visualizes your contributions. + +## Example Configuration + +Here's a sample `report-config.yaml` file for a student showcasing their work across several projects: + +```yaml +title: My Code Portfolio +repos: + - repo: https://github.com/RepoSense/reposense.git + groups: + - group-name: code + globs: + - "**.java" + branches: + - branch: master + blurb: "Reposense is a code contribution analysis tool which I contributed." + authors: + - author-git-host-id: lyuanww + author-display-name: Li Yuan + author-emails: + - user@gmail.com + - e0123456@u.nus.edu + - repo: https://github.com/lyuanww/ip.git + groups: + - group-name: code + globs: + - "**.java" + branches: + - branch: master + blurb: "A task manager chat bot implemented in Java." + authors: + - author-git-host-id: lyuanww + author-display-name: Li Yuan + author-emails: + - user@gmail.com + - e0123456@u.nus.edu + - repo: https://github.com/lyuanww/tp.git + groups: + - group-name: code + globs: + - "**.java" + branches: + - branch: master + blurb: "A patient management system implemented in Java." + authors: + - author-git-host-id: lyuanww + author-display-name: Li Yuan + author-emails: + - user@gmail.com + - e0123456@u.nus.edu +``` +### Sample report generated +![report](../images/report-config-report.png) + +## Further Customizing Your Report + +Optionally, you can provide more detailed descriptions to your report such as an introduction at the top of your dashboard or explanatory blurbs for each repository. Please refer to this [section](./customizingReports.md#personalizing-reports). + +## Advanced Report Configuration + +For users who need more advanced configuration options, `report-config.yaml` offers many additional features beyond the basic setup. The following section explains the complete syntax and capabilities. + +### Complete `report-config.yaml` Example + +```yaml +title: RepoSense Report +repos: + - repo: https://github.com/reposense/publish-RepoSense.git + groups: + - group-name: code + globs: + - "**.py" + - group-name: tests + globs: + - "src/test**" + - group-name: docs + globs: + - "docs**" + - "**.adoc" + - "**.md" + branches: + - branch: master + blurb: "My project" + authors: + - author-git-host-id: jedkohjk + author-display-name: jedkohjk + author-git-author-name: jedkohjk + author-emails: + - email1@example.com + - email2@example.com + ignore-authors-list: + - bot + ignore-glob-list: + - "**.in" + file-size-limit: 2000000 +``` + +### Field Descriptions +Note: All fields are optional unless specified otherwise. + +#### Top-Level Fields + +* `title`: Sets the title of your generated report, which appears as the title of the deployed dashboard. + * Default: "RepoSense Report". +* `repos`: A list of repositories to include in your analysis.. + * This field is an array, so you can include multiple repositories. + +#### Repository-Level Fields + +For each repository in the `repos` list, you can specify: + +* `repo` {{ mandatory }} : The URL to the repository you want to analyze. + * Example: `https://github.com/RepoSense/reposense.git` +* `groups`: Allows you to define custom groupings of files for more organized analysis. + * This is useful for separating code files, test files, documentation, etc. + * Each group has: + * `group-name` {{ mandatory }} : A name for the group (e.g., "code", "tests", "docs"). + * `globs` {{ mandatory }} : File patterns to include in this group using [glob format](https://docs.oracle.com/javase/tutorial/essential/io/fileOps.html#glob). +* `branches` {{ mandatory }} : The branches you want to analyze in the repository. + * For each branch, you specify: + * `branch`: The name of the branch (e.g., "master", "main", "develop"). + * Default: The default branch of the repository. + * `blurb`: A short description of the branch that appears in the report. + * For more detailed descriptions, you can use a separate `blurbs.md` file. + +#### Author Configuration + +Within each branch, you can specify: + +* `authors`: A list of authors whose contributions you want to track. If none specified, all authors will be shown. + * For each author: + * `author-git-host-id` {{ mandatory }} : The GitHub username of the author. + * `author-display-name`: The name to display in the report (can be different from the GitHub username). + * `author-git-author-name`: The name used in Git commits. + * `author-emails`: A list of email addresses associated with the author's commits. + +#### Filtering Options + +* `ignore-authors-list`: Authors to exclude from the analysis. + * Specified by their Git Author Name. + * Useful for excluding bots or automated commit accounts. +* `ignore-glob-list`: Files or directories to exclude from analysis. + * Uses the [glob format](https://docs.oracle.com/javase/tutorial/essential/io/fileOps.html#glob). + * Example: `"**.in"` excludes all files with the ".in" extension. +* `file-size-limit`: Maximum file size (in bytes) for analysis. + * Files larger than this limit will be ignored. + * Overrides the default file size limit. diff --git a/frontend/cypress/configs/default/report-config.json b/frontend/cypress/configs/default/report-config.json deleted file mode 100644 index ea98e619e3..0000000000 --- a/frontend/cypress/configs/default/report-config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "title": "RepoSense Test Report" -} diff --git a/frontend/cypress/configs/default/report-config.yaml b/frontend/cypress/configs/default/report-config.yaml new file mode 100644 index 0000000000..a5d9bb7897 --- /dev/null +++ b/frontend/cypress/configs/default/report-config.yaml @@ -0,0 +1 @@ +title: RepoSense Test Report diff --git a/frontend/cypress/configs/portfolio/report-config.json b/frontend/cypress/configs/portfolio/report-config.json deleted file mode 100644 index ea98e619e3..0000000000 --- a/frontend/cypress/configs/portfolio/report-config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "title": "RepoSense Test Report" -} diff --git a/frontend/cypress/configs/portfolio/report-config.yaml b/frontend/cypress/configs/portfolio/report-config.yaml new file mode 100644 index 0000000000..a5d9bb7897 --- /dev/null +++ b/frontend/cypress/configs/portfolio/report-config.yaml @@ -0,0 +1 @@ +title: RepoSense Test Report diff --git a/src/main/java/reposense/RepoSense.java b/src/main/java/reposense/RepoSense.java index c6d32f9a29..5c4740ae1b 100644 --- a/src/main/java/reposense/RepoSense.java +++ b/src/main/java/reposense/RepoSense.java @@ -14,8 +14,8 @@ import reposense.model.CliArguments; import reposense.model.RepoBlurbMap; import reposense.model.RepoConfiguration; -import reposense.model.ReportConfiguration; import reposense.model.RunConfigurationDecider; +import reposense.model.reportconfig.ReportConfiguration; import reposense.parser.ArgsParser; import reposense.parser.exceptions.InvalidCsvException; import reposense.parser.exceptions.InvalidHeaderException; @@ -56,7 +56,7 @@ public static void main(String[] args) { configs = RunConfigurationDecider.getRunConfiguration(cliArguments).getRepoConfigurations(); reportConfig = cliArguments.getReportConfiguration(); - repoBlurbMap = cliArguments.getRepoBlurbMap(); + repoBlurbMap = cliArguments.mergeWithReportConfigRepoBlurbMap(); authorBlurbMap = cliArguments.getAuthorBlurbMap(); RepoConfiguration.setFormatsToRepoConfigs(configs, cliArguments.getFormats()); diff --git a/src/main/java/reposense/model/CliArguments.java b/src/main/java/reposense/model/CliArguments.java index 0391839fef..692ab94384 100644 --- a/src/main/java/reposense/model/CliArguments.java +++ b/src/main/java/reposense/model/CliArguments.java @@ -5,13 +5,15 @@ import java.time.LocalDateTime; import java.time.ZoneId; import java.util.List; +import java.util.Map; import java.util.Objects; +import reposense.model.reportconfig.ReportConfiguration; import reposense.parser.ArgsParser; import reposense.parser.AuthorConfigCsvParser; import reposense.parser.GroupConfigCsvParser; import reposense.parser.RepoConfigCsvParser; -import reposense.parser.ReportConfigJsonParser; +import reposense.parser.ReportConfigYamlParser; /** * Represents command line arguments user supplied when running the program. @@ -168,6 +170,22 @@ public AuthorBlurbMap getAuthorBlurbMap() { return authorBlurbMap; } + /** + * Merges the {@code blurbMap} from the blurbs file with the blurb map in {@code reportConfiguration}. + * + * @return the merged blurb map. + */ + public RepoBlurbMap mergeWithReportConfigRepoBlurbMap() { + if (reportConfiguration == null) { + return repoBlurbMap; + } + RepoBlurbMap repoConfigRepoBlurbMap = reportConfiguration.getRepoBlurbMap(); + for (Map.Entry entry : repoBlurbMap.getAllMappings().entrySet()) { + repoConfigRepoBlurbMap.withRecord(entry.getKey(), entry.getValue()); + } + return repoConfigRepoBlurbMap; + } + public boolean isViewModeOnly() { return isViewModeOnly; } @@ -180,6 +198,10 @@ public double getOriginalityThreshold() { return originalityThreshold; } + public boolean areReportConfigRepositoriesConfigured() { + return reportConfiguration != null && !reportConfiguration.getReportRepoConfigurations().isEmpty(); + } + public boolean isPortfolio() { return isPortfolio; } @@ -461,7 +483,7 @@ public Builder configFolderPath(Path configFolderPath) { this.cliArguments.groupConfigFilePath = configFolderPath.resolve( GroupConfigCsvParser.GROUP_CONFIG_FILENAME); this.cliArguments.reportConfigFilePath = configFolderPath.resolve( - ReportConfigJsonParser.REPORT_CONFIG_FILENAME); + ReportConfigYamlParser.REPORT_CONFIG_FILENAME); return this; } diff --git a/src/main/java/reposense/model/OneStopConfigRunConfiguration.java b/src/main/java/reposense/model/OneStopConfigRunConfiguration.java new file mode 100644 index 0000000000..98fd7ab1cc --- /dev/null +++ b/src/main/java/reposense/model/OneStopConfigRunConfiguration.java @@ -0,0 +1,78 @@ +package reposense.model; + +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; + +import reposense.model.reportconfig.ReportAuthorDetails; +import reposense.model.reportconfig.ReportBranchData; +import reposense.model.reportconfig.ReportConfiguration; +import reposense.model.reportconfig.ReportRepoConfiguration; +import reposense.parser.exceptions.InvalidLocationException; +import reposense.system.LogsManager; + +/** + * Represents RepoSense run configured by the one-stop configuration file. + */ +public class OneStopConfigRunConfiguration implements RunConfiguration { + private static final Logger logger = LogsManager.getLogger(OneStopConfigRunConfiguration.class); + + private final CliArguments cliArguments; + + public OneStopConfigRunConfiguration(CliArguments cliArguments) { + this.cliArguments = cliArguments; + } + + /** + * Constructs a list of {@link RepoConfiguration}. + * + * @throws InvalidLocationException if the location specified in the config file is invalid. + */ + @Override + public List getRepoConfigurations() throws InvalidLocationException { + ReportConfiguration reportConfiguration = this.cliArguments.getReportConfiguration(); + List repoConfigs = new ArrayList<>(); + List authorConfigs = new ArrayList<>(); + List groupConfigs = new ArrayList<>(); + + for (ReportRepoConfiguration rrc : reportConfiguration.getReportRepoConfigurations()) { + logger.info("Parsing " + rrc.getRepo() + "..."); + RepoLocation repoLocation = new RepoLocation(rrc.getRepo()); + groupConfigs.add(rrc.getGroupConfiguration(repoLocation)); + + for (ReportBranchData rbd : rrc.getBranches()) { + logger.info("Parsing " + rbd.getBranch() + "..."); + + RepoConfiguration.Builder builder = new RepoConfiguration.Builder() + .location(repoLocation) + .branch(rbd.getBranch()) + .ignoreGlobList(rbd.getIgnoreGlobList()) + .ignoredAuthorsList(rbd.getIgnoreAuthorList()) + .fileSizeLimit(rbd.getFileSizeLimit()) + // Needs to be removed this when we deprecate the standalone config + .isStandaloneConfigIgnored(true); + + AuthorConfiguration authorConfiguration = new AuthorConfiguration(repoLocation, rbd.getBranch()); + for (ReportAuthorDetails rad : rbd.getReportAuthorDetails()) { + logger.info("Parsing " + rad.getAuthorGitHostId() + "..."); + + Author author = new Author(rad.getAuthorGitHostId()); + author.setEmails(rad.getAuthorEmails()); + author.setDisplayName(rad.getAuthorDisplayName()); + author.setAuthorAliases(List.of(rad.getAuthorGitAuthorName())); + + authorConfiguration.addAuthor(author); + } + authorConfigs.add(authorConfiguration); + repoConfigs.add(builder.build()); + } + } + + logger.info("Merging author, group and repo configurations..."); + RepoConfiguration.merge(repoConfigs, authorConfigs); + RepoConfiguration.setGroupConfigsToRepos(repoConfigs, groupConfigs); + + logger.info("Finished parsing OneStopConfigRunConfiguration!"); + return repoConfigs; + } +} diff --git a/src/main/java/reposense/model/ReportConfiguration.java b/src/main/java/reposense/model/ReportConfiguration.java deleted file mode 100644 index e06bfde17a..0000000000 --- a/src/main/java/reposense/model/ReportConfiguration.java +++ /dev/null @@ -1,19 +0,0 @@ -package reposense.model; - -/** - * Represents configuration information from JSON config file for generated report. - */ -public class ReportConfiguration { - private static final String DEFAULT_TITLE = "RepoSense Report"; - private String title; - - public ReportConfiguration() {} - - public ReportConfiguration(String title) { - this.title = title; - } - - public String getTitle() { - return (title == null) ? DEFAULT_TITLE : title; - } -} diff --git a/src/main/java/reposense/model/RunConfigurationDecider.java b/src/main/java/reposense/model/RunConfigurationDecider.java index c4bd07c85b..6a3cf2ebbc 100644 --- a/src/main/java/reposense/model/RunConfigurationDecider.java +++ b/src/main/java/reposense/model/RunConfigurationDecider.java @@ -8,6 +8,11 @@ public static RunConfiguration getRunConfiguration(CliArguments cliArguments) { if (cliArguments.getLocations() != null) { return new CliRunConfiguration(cliArguments); } + + if (cliArguments.areReportConfigRepositoriesConfigured()) { + return new OneStopConfigRunConfiguration(cliArguments); + } + return new ConfigRunConfiguration(cliArguments); } } diff --git a/src/main/java/reposense/model/reportconfig/ReportAuthorDetails.java b/src/main/java/reposense/model/reportconfig/ReportAuthorDetails.java new file mode 100644 index 0000000000..f4fd31456f --- /dev/null +++ b/src/main/java/reposense/model/reportconfig/ReportAuthorDetails.java @@ -0,0 +1,66 @@ +package reposense.model.reportconfig; + +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Represents an author's details in the report-config.yaml file. + */ +public class ReportAuthorDetails { + private final List authorEmails; + private final String authorGitHostId; + private final String authorDisplayName; + private final String authorGitAuthorName; + + @JsonCreator + public ReportAuthorDetails( + @JsonProperty("author-emails") List authorEmails, + @JsonProperty("author-git-host-id") String authorGitHostId, + @JsonProperty("author-display-name") String authorDisplayName, + @JsonProperty("author-git-author-name") String authorGitAuthorName) { + if (authorGitHostId == null) { + throw new IllegalArgumentException("Author Git Host ID cannot be empty."); + } + this.authorGitHostId = authorGitHostId; + this.authorEmails = authorEmails == null ? new ArrayList<>() : authorEmails; + this.authorDisplayName = authorDisplayName == null ? "" : authorDisplayName; + this.authorGitAuthorName = authorGitAuthorName == null ? "" : authorGitAuthorName; + } + + public List getAuthorEmails() { + return authorEmails; + } + + public String getAuthorGitHostId() { + return authorGitHostId; + } + + public String getAuthorDisplayName() { + return authorDisplayName; + } + + public String getAuthorGitAuthorName() { + return authorGitAuthorName; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (obj instanceof ReportAuthorDetails) { + ReportAuthorDetails rad = (ReportAuthorDetails) obj; + return rad.getAuthorEmails().equals(this.getAuthorEmails()) + && rad.getAuthorGitHostId().equals(this.getAuthorGitHostId()) + && rad.getAuthorDisplayName().equals(this.getAuthorDisplayName()) + && rad.getAuthorGitAuthorName().equals(this.getAuthorGitAuthorName()); + } + + return false; + } +} + diff --git a/src/main/java/reposense/model/reportconfig/ReportBranchData.java b/src/main/java/reposense/model/reportconfig/ReportBranchData.java new file mode 100644 index 0000000000..f1de0edef7 --- /dev/null +++ b/src/main/java/reposense/model/reportconfig/ReportBranchData.java @@ -0,0 +1,81 @@ +package reposense.model.reportconfig; + +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Represents a single entry of a branch in the YAML config file. + */ +public class ReportBranchData { + public static final String DEFAULT_BRANCH = "HEAD"; + public static final Long DEFAULT_FILE_SIZE_LIMIT = 1000000L; + + private final String branch; + private final String blurb; + private final List reportAuthorDetails; + private final List ignoreGlobList; + private final List ignoreAuthorList; + private final Long fileSizeLimit; + + @JsonCreator + public ReportBranchData( + @JsonProperty("branch") String branch, + @JsonProperty("blurb") String blurb, + @JsonProperty("authors") List reportAuthorDetails, + @JsonProperty("ignore-glob-list") List ignoreGlobList, + @JsonProperty("ignore-authors-list") List ignoreAuthorList, + @JsonProperty("file-size-limit") Long fileSizeLimit) { + this.branch = branch == null ? DEFAULT_BRANCH : branch; + this.blurb = blurb == null ? "" : blurb; + this.reportAuthorDetails = reportAuthorDetails == null ? new ArrayList<>() : reportAuthorDetails; + this.ignoreGlobList = ignoreGlobList == null ? new ArrayList<>() : ignoreGlobList; + this.ignoreAuthorList = ignoreAuthorList == null ? new ArrayList<>() : ignoreAuthorList; + this.fileSizeLimit = fileSizeLimit == null ? DEFAULT_FILE_SIZE_LIMIT : fileSizeLimit; + } + + public String getBranch() { + return branch; + } + + public String getBlurb() { + return blurb; + } + + public List getReportAuthorDetails() { + return reportAuthorDetails; + } + + public List getIgnoreGlobList() { + return ignoreGlobList; + } + + public List getIgnoreAuthorList() { + return ignoreAuthorList; + } + + public Long getFileSizeLimit() { + return fileSizeLimit; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (obj instanceof ReportBranchData) { + ReportBranchData rbd = (ReportBranchData) obj; + return this.getBranch().equals(rbd.getBranch()) + && this.getBlurb().equals(rbd.getBlurb()) + && this.getReportAuthorDetails().equals(rbd.getReportAuthorDetails()) + && this.getIgnoreGlobList().equals(rbd.getIgnoreGlobList()) + && this.getIgnoreAuthorList().equals(rbd.getIgnoreAuthorList()) + && this.getFileSizeLimit().equals(rbd.getFileSizeLimit()); + } + + return false; + } +} diff --git a/src/main/java/reposense/model/reportconfig/ReportConfiguration.java b/src/main/java/reposense/model/reportconfig/ReportConfiguration.java new file mode 100644 index 0000000000..8e7da609f6 --- /dev/null +++ b/src/main/java/reposense/model/reportconfig/ReportConfiguration.java @@ -0,0 +1,80 @@ +package reposense.model.reportconfig; + +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import reposense.model.RepoBlurbMap; +import reposense.system.LogsManager; + +/** + * Class that contains information on a report's configurations. + * This class is used mainly for quickly setting up one's personal code portfolio. + */ +public class ReportConfiguration { + public static final String DEFAULT_TITLE = "RepoSense Report"; + + private static final Logger logger = LogsManager.getLogger(ReportConfiguration.class); + + private String title; + private List reportRepoConfigurations; + + public ReportConfiguration() {} + + @JsonCreator + public ReportConfiguration( + @JsonProperty("title") String title, + @JsonProperty("repos") List reportRepoConfigurations) { + this.title = title == null ? DEFAULT_TITLE : title; + this.reportRepoConfigurations = reportRepoConfigurations == null ? new ArrayList<>() : reportRepoConfigurations; + } + + /** + * Converts the {@code ReportRepoConfiguration} list into a {@code BlurbMap}. + * + * @return {@code BlurbMap} containing the repository name and its associated blurb. + */ + public RepoBlurbMap getRepoBlurbMap() { + RepoBlurbMap blurbMap = new RepoBlurbMap(); + + for (ReportRepoConfiguration repoConfig : reportRepoConfigurations) { + try { + for (ReportRepoConfiguration.MapEntry repoNameBlurbPair + : repoConfig.getFullyQualifiedRepoNamesWithBlurbs()) { + blurbMap.withRecord(repoNameBlurbPair.getKey(), repoNameBlurbPair.getValue()); + } + } catch (IllegalArgumentException ex) { + logger.log(Level.WARNING, ex.getMessage(), ex); + } + } + + return blurbMap; + } + + public String getTitle() { + return title; + } + + public List getReportRepoConfigurations() { + return reportRepoConfigurations; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (obj instanceof ReportConfiguration) { + ReportConfiguration rc = (ReportConfiguration) obj; + return rc.getTitle().equals(this.getTitle()) + && rc.getReportRepoConfigurations().equals(this.getReportRepoConfigurations()); + } + + return false; + } +} diff --git a/src/main/java/reposense/model/reportconfig/ReportGroupNameAndGlobs.java b/src/main/java/reposense/model/reportconfig/ReportGroupNameAndGlobs.java new file mode 100644 index 0000000000..65b49791cd --- /dev/null +++ b/src/main/java/reposense/model/reportconfig/ReportGroupNameAndGlobs.java @@ -0,0 +1,76 @@ +package reposense.model.reportconfig; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import reposense.model.FileType; + +/** + * Contains details about each report group and the corresponding globs. + */ +public class ReportGroupNameAndGlobs { + private final String groupName; + private final List globs; + + @JsonCreator + public ReportGroupNameAndGlobs( + @JsonProperty("group-name") String groupName, + @JsonProperty("globs") List globs) { + validate(groupName, globs); + this.groupName = groupName; + this.globs = globs; + } + + /** + * Validates the group name and globs. + * + * @param groupName the name of the group. + * @param globs the list of globs. + * @throws IllegalArgumentException if the group name or globs is invalid. + */ + private static void validate(String groupName, List globs) throws IllegalArgumentException { + if (groupName == null) { + throw new IllegalArgumentException("Group name cannot be empty."); + } + if (globs == null) { + throw new IllegalArgumentException("Globs cannot be empty."); + } + } + + public String getGroupName() { + return groupName; + } + + public List getGlobs() { + return globs; + } + + /** + * Converts this {@code ReportGroupNameAndGlobs} into a {@code FileType}. + * + * @return Adapted {@code FileType} object. + */ + public FileType toFileType() { + return new FileType( + this.getGroupName(), + this.getGlobs() + ); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (obj instanceof ReportGroupNameAndGlobs) { + ReportGroupNameAndGlobs rgnag = (ReportGroupNameAndGlobs) obj; + return rgnag.getGroupName().equals(this.getGroupName()) + && rgnag.getGlobs().equals(this.getGlobs()); + } + + return false; + } +} diff --git a/src/main/java/reposense/model/reportconfig/ReportRepoConfiguration.java b/src/main/java/reposense/model/reportconfig/ReportRepoConfiguration.java new file mode 100644 index 0000000000..d07ba202fc --- /dev/null +++ b/src/main/java/reposense/model/reportconfig/ReportRepoConfiguration.java @@ -0,0 +1,125 @@ +package reposense.model.reportconfig; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import reposense.model.GroupConfiguration; +import reposense.model.RepoLocation; + +/** + * Represents a single repository configuration in the overall report + * configuration. + */ +public class ReportRepoConfiguration { + private final String repo; + private final List groups; + private final List branches; + + @JsonCreator + public ReportRepoConfiguration( + @JsonProperty("repo") String repo, + @JsonProperty("groups") List groups, + @JsonProperty("branches") List branches) { + if (repo == null) { + throw new IllegalArgumentException("Repo URL cannot be empty."); + } + this.repo = repo; + this.groups = groups == null ? new ArrayList<>() : groups; + this.branches = branches == null ? new ArrayList<>() : branches; + } + + /** + * Represents a single mapped entry between a fully qualified repository name and its associated blurb. + */ + public static final class MapEntry { + private final String key; + private final String value; + + public MapEntry(String key, String value) { + this.key = key; + this.value = value; + } + + public String getKey() { + return key; + } + + public String getValue() { + return value; + } + } + + public String getRepo() { + return repo; + } + + /** + * Returns the repository name from the {@code repo} URL. Each entry is represented by a list containing + * the fully qualified repository name and the associated blurb. + * + * @return {@code List} containing the fully qualified repository name and the associated blurb. + * @throws IllegalArgumentException if the {@code repo} URL is not in the correct format. + */ + public List getFullyQualifiedRepoNamesWithBlurbs() { + List repoNames = new ArrayList<>(); + Pattern pattern = Pattern.compile("\\.git$"); + Matcher matcher = pattern.matcher(getRepo()); + + if (!matcher.find()) { + // no point continuing if there are no blurbs + throw new IllegalArgumentException("Repo URL: " + this.getRepo() + " is not in the correct format. " + + "Skipping..."); + } + + for (ReportBranchData rbd : this.getBranches()) { + String qualifiedName = getRepo().substring(0, matcher.start()) + "/tree/" + rbd.getBranch(); + repoNames.add(new MapEntry(qualifiedName, rbd.getBlurb())); + } + + return repoNames; + } + + public List getGroupDetails() { + return groups; + } + + /** + * Merges all {@code ReportGroupNameAndGlobs} objects in {@code groups} into a {@code GroupConfiguration} object. + * + * @param location {@code RepoLocation} object. + * @return Adapted {@code GroupConfiguration} object. + */ + public GroupConfiguration getGroupConfiguration(RepoLocation location) { + GroupConfiguration groupConfiguration = new GroupConfiguration(location); + + this.getGroupDetails() + .forEach(x -> groupConfiguration.addGroup(x.toFileType())); + + return groupConfiguration; + } + + public List getBranches() { + return branches; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (obj instanceof ReportRepoConfiguration) { + ReportRepoConfiguration rrc = (ReportRepoConfiguration) obj; + return rrc.getRepo().equals(this.getRepo()) + && rrc.getGroupDetails().equals(this.getGroupDetails()) + && rrc.getBranches().equals(this.getBranches()); + } + + return false; + } +} diff --git a/src/main/java/reposense/parser/ArgsParser.java b/src/main/java/reposense/parser/ArgsParser.java index 5bab4a4d43..1f51a50b7b 100644 --- a/src/main/java/reposense/parser/ArgsParser.java +++ b/src/main/java/reposense/parser/ArgsParser.java @@ -9,6 +9,7 @@ import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.logging.Level; import java.util.logging.Logger; import com.google.gson.JsonSyntaxException; @@ -28,7 +29,7 @@ import reposense.model.CliArguments; import reposense.model.FileType; import reposense.model.RepoBlurbMap; -import reposense.model.ReportConfiguration; +import reposense.model.reportconfig.ReportConfiguration; import reposense.parser.exceptions.InvalidMarkdownException; import reposense.parser.exceptions.ParseException; import reposense.parser.types.AlphanumericArgumentType; @@ -91,7 +92,7 @@ public class ArgsParser { private static final String MESSAGE_USING_DEFAULT_CONFIG_PATH = "Config path not provided, using the config folder as default."; private static final String MESSAGE_INVALID_CONFIG_PATH = "%s is malformed."; - private static final String MESSAGE_INVALID_CONFIG_JSON = "%s Ignoring the report config provided."; + private static final String MESSAGE_INVALID_CONFIG_YAML = "%s Ignoring the report config provided."; private static final String MESSAGE_INVALID_MARKDOWN_BLURBS = "%s Ignoring the blurb file 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."; @@ -380,26 +381,24 @@ public static CliArguments parse(String[] args) throws HelpScreenException, Pars * @param results Parsed results of the user-supplied CLI arguments. */ private static void addReportConfigToBuilder(CliArguments.Builder builder, Namespace results) { - ReportConfiguration reportConfig = new ReportConfiguration(); List locations = results.get(REPO_FLAGS[0]); Path configFolderPath = results.get(CONFIG_FLAGS[0]); // Report config is ignored if --repos is provided if (locations == null) { - Path reportConfigFilePath = configFolderPath.resolve(ReportConfigJsonParser.REPORT_CONFIG_FILENAME); + Path reportConfigFilePath = configFolderPath.resolve(ReportConfigYamlParser.REPORT_CONFIG_FILENAME); try { - reportConfig = new ReportConfigJsonParser().parse(reportConfigFilePath); + ReportConfiguration reportConfig = new ReportConfigYamlParser().parse(reportConfigFilePath); + builder.reportConfiguration(reportConfig); } catch (JsonSyntaxException jse) { logger.warning(String.format(MESSAGE_INVALID_CONFIG_PATH, reportConfigFilePath)); - } catch (IllegalArgumentException iae) { - logger.warning(String.format(MESSAGE_INVALID_CONFIG_JSON, iae.getMessage())); } catch (IOException ioe) { - // IOException thrown as report-config.json is not found. - // Ignore exception as the file is optional. + // IOException thrown as report-config.yaml is not found or fields are invalid. + logger.log(Level.WARNING, "Error parsing report-config.yaml: " + ioe.getMessage() + "\n" + + String.format(MESSAGE_INVALID_CONFIG_YAML, reportConfigFilePath)); } } - builder.reportConfiguration(reportConfig); } /** diff --git a/src/main/java/reposense/parser/ReportConfigJsonParser.java b/src/main/java/reposense/parser/ReportConfigJsonParser.java deleted file mode 100644 index f200fc712a..0000000000 --- a/src/main/java/reposense/parser/ReportConfigJsonParser.java +++ /dev/null @@ -1,34 +0,0 @@ -package reposense.parser; - -import java.io.IOException; -import java.lang.reflect.Type; -import java.nio.file.Path; - -import com.google.gson.reflect.TypeToken; - -import reposense.model.ReportConfiguration; - -/** - * Parses json file from {@link Path} and creates a new {@link ReportConfiguration} object. - */ -public class ReportConfigJsonParser extends JsonParser { - public static final String REPORT_CONFIG_FILENAME = "report-config.json"; - - /** - * Gets the type of {@link ReportConfiguration} for json conversion. - */ - @Override - public Type getType() { - return new TypeToken(){}.getType(); - } - - /** - * Converts json file from the given {@code path} and returns a {@link ReportConfiguration} object. - * - * @throws IOException if {@code path} is invalid. - */ - @Override - public ReportConfiguration parse(Path path) throws IOException { - return fromJson(path); - } -} diff --git a/src/main/java/reposense/parser/ReportConfigYamlParser.java b/src/main/java/reposense/parser/ReportConfigYamlParser.java new file mode 100644 index 0000000000..8206fdf48f --- /dev/null +++ b/src/main/java/reposense/parser/ReportConfigYamlParser.java @@ -0,0 +1,47 @@ +package reposense.parser; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Type; +import java.nio.file.Path; +import java.util.logging.Level; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; + +import reposense.model.reportconfig.ReportConfiguration; + +/** + * YAML Parser for report-config.yaml files. + */ +public class ReportConfigYamlParser extends YamlParser { + public static final String REPORT_CONFIG_FILENAME = "report-config.yaml"; + public static final String REPORT_CONFIG_PARSED_SUCCESSFULLY_MESSAGE = + "report-config.yaml file parsed successfully!"; + + @Override + public Type getType() { + return ReportConfiguration.class; + } + + /** + * Parses the YAML file at {@code path}. + * + * @param path Path to the YAML file + * @return Parsed {@code ReportConfiguration} object + * @throws IOException if the provided path is invalid + */ + @Override + public ReportConfiguration parse(Path path) throws IOException { + // adapted from https://www.baeldung.com/jackson-yaml + ReportConfiguration reportConfiguration; + + logger.log(Level.INFO, "Parsing report-config.yaml file..."); + ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); + mapper.findAndRegisterModules(); + reportConfiguration = mapper.readValue(new File(path.toString()), ReportConfiguration.class); + logger.log(Level.INFO, REPORT_CONFIG_PARSED_SUCCESSFULLY_MESSAGE); + + return reportConfiguration; + } +} diff --git a/src/main/java/reposense/parser/YamlParser.java b/src/main/java/reposense/parser/YamlParser.java new file mode 100644 index 0000000000..5c47407e18 --- /dev/null +++ b/src/main/java/reposense/parser/YamlParser.java @@ -0,0 +1,32 @@ +package reposense.parser; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.nio.file.Path; +import java.util.logging.Logger; + +import reposense.system.LogsManager; + +/** + * Represents a YAML parser that is able to parse a YAML file from a {@link Path} into an object of + * type {@code T}. + * + * @param Type {@code T} that this parser can parse and return as an object + */ +public abstract class YamlParser { + protected static final Logger logger = LogsManager.getLogger(YamlParser.class); + + /** + * Returns the type of {@code T} for YAML file conversion. + */ + public abstract Type getType(); + + /** + * Converts the YAML file from the given {@code path} into object of type {@code T} and return it. + * + * @param path Path to the YAML file + * @return Parsed object of type {@code T} + * @throws IOException if the {@code path} is invalid + */ + public abstract T parse(Path path) throws IOException; +} diff --git a/src/main/java/reposense/parser/types/ConfigFolderArgumentType.java b/src/main/java/reposense/parser/types/ConfigFolderArgumentType.java index 4b75ba06cc..89c56cf1f9 100644 --- a/src/main/java/reposense/parser/types/ConfigFolderArgumentType.java +++ b/src/main/java/reposense/parser/types/ConfigFolderArgumentType.java @@ -10,13 +10,14 @@ import net.sourceforge.argparse4j.inf.ArgumentParserException; import net.sourceforge.argparse4j.inf.ArgumentType; import reposense.parser.RepoConfigCsvParser; +import reposense.parser.ReportConfigYamlParser; /** * Checks the argument of {@code --config} flag. */ public class ConfigFolderArgumentType implements ArgumentType { private static final String PARSE_EXCEPTION_MESSAGE_MISSING_REQUIRED_CONFIG_FILES = - "The required config file %s is not found in the specified folder."; + "The required config file %s or %s is not found in the specified folder."; @Override public Path convert(ArgumentParser parser, Argument arg, String value) throws ArgumentParserException { @@ -27,7 +28,11 @@ public Path convert(ArgumentParser parser, Argument arg, String value) throws Ar return Paths.get(value); } + if (Files.exists(Paths.get(value).resolve(ReportConfigYamlParser.REPORT_CONFIG_FILENAME))) { + return Paths.get(value); + } + throw new ArgumentParserException(String.format(PARSE_EXCEPTION_MESSAGE_MISSING_REQUIRED_CONFIG_FILES, - RepoConfigCsvParser.REPO_CONFIG_FILENAME), parser); + RepoConfigCsvParser.REPO_CONFIG_FILENAME, ReportConfigYamlParser.REPORT_CONFIG_FILENAME), parser); } } diff --git a/src/main/java/reposense/report/ReportGenerator.java b/src/main/java/reposense/report/ReportGenerator.java index c3e60d074c..8653f3fb2a 100644 --- a/src/main/java/reposense/report/ReportGenerator.java +++ b/src/main/java/reposense/report/ReportGenerator.java @@ -46,8 +46,8 @@ import reposense.model.RepoBlurbMap; import reposense.model.RepoConfiguration; import reposense.model.RepoLocation; -import reposense.model.ReportConfiguration; import reposense.model.StandaloneConfig; +import reposense.model.reportconfig.ReportConfiguration; import reposense.parser.StandaloneConfigJsonParser; import reposense.parser.exceptions.InvalidMarkdownException; import reposense.report.exception.NoAuthorsWithCommitsFoundException; diff --git a/src/main/java/reposense/report/SummaryJson.java b/src/main/java/reposense/report/SummaryJson.java index adb10c0c3a..ba29fcdff7 100644 --- a/src/main/java/reposense/report/SummaryJson.java +++ b/src/main/java/reposense/report/SummaryJson.java @@ -11,8 +11,8 @@ import reposense.model.AuthorBlurbMap; import reposense.model.RepoBlurbMap; import reposense.model.RepoConfiguration; -import reposense.model.ReportConfiguration; import reposense.model.SupportedDomainUrlMap; +import reposense.model.reportconfig.ReportConfiguration; import reposense.parser.SummaryJsonParser; /** @@ -66,9 +66,10 @@ public SummaryJson(List repos, ReportConfiguration reportConf boolean isUntilDateProvided, String repoSenseVersion, Set> errorSet, String reportGenerationTime, ZoneId zoneId, boolean isAuthorshipAnalyzed, RepoBlurbMap repoBlurbs, AuthorBlurbMap authorBlurbs, boolean isPortfolio) { - this(repos, reportConfig.getTitle(), reportGeneratedTime, sinceDate, untilDate, isSinceDateProvided, - isUntilDateProvided, repoSenseVersion, errorSet, reportGenerationTime, zoneId, isAuthorshipAnalyzed, - repoBlurbs, authorBlurbs, isPortfolio); + + this(repos, reportConfig == null ? ReportConfiguration.DEFAULT_TITLE : reportConfig.getTitle(), + reportGeneratedTime, sinceDate, untilDate, isSinceDateProvided, isUntilDateProvided, repoSenseVersion, + errorSet, reportGenerationTime, zoneId, isAuthorshipAnalyzed, repoBlurbs, authorBlurbs, isPortfolio); } @Override diff --git a/src/systemtest/java/reposense/ReportConfigSystemTest.java b/src/systemtest/java/reposense/ReportConfigSystemTest.java new file mode 100644 index 0000000000..4521f147f2 --- /dev/null +++ b/src/systemtest/java/reposense/ReportConfigSystemTest.java @@ -0,0 +1,163 @@ +package reposense; + +import static org.apache.tools.ant.types.Commandline.translateCommandline; +import static reposense.util.TestUtil.loadResource; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.parallel.Execution; +import org.junit.jupiter.api.parallel.ExecutionMode; + +import reposense.model.SupportedDomainUrlMap; +import reposense.parser.types.SinceDateArgumentType; +import reposense.report.ErrorSummary; +import reposense.util.FileUtil; +import reposense.util.InputBuilder; +import reposense.util.SystemTestUtil; + +@Execution(ExecutionMode.SAME_THREAD) +public class ReportConfigSystemTest { + private static final List TESTING_FILE_FORMATS = Arrays.asList("py", "sh"); + private static final String TEST_TIME_ZONE = "Asia/Singapore"; + + private static final String OUTPUT_DIRECTORY = "rc_temp"; + private static final Path REPORT_DIRECTORY_PATH = Paths.get(OUTPUT_DIRECTORY, "reposense-report"); + + private static boolean didNotCloneRepoNormally = true; + + @BeforeEach + public void setUp() throws Exception { + SupportedDomainUrlMap.clearAccessedSet(); + FileUtil.deleteDirectory(OUTPUT_DIRECTORY); + ErrorSummary.getInstance().clearErrorSet(); + } + + @AfterEach + public void tearDown() throws Exception { + FileUtil.deleteDirectory(OUTPUT_DIRECTORY); + } + + /** + * System test with a specified until date and a {@link SinceDateArgumentType#FIRST_COMMIT_DATE_SHORTHAND} + * since date to capture from the first commit. + */ + @Test + public void testSinceBeginningDateRange() { + InputBuilder inputBuilder = initInputBuilder() + .addSinceDate(SinceDateArgumentType.FIRST_COMMIT_DATE_SHORTHAND) + .addUntilDate("31/12/2024"); + + runTest(inputBuilder, false, + "ReportConfigSystemTest/sinceBeginningDateRange/expected"); + } + + @Test + public void test30DaysFromUntilDate() { + InputBuilder inputBuilder = initInputBuilder().addUntilDate("31/8/2024"); + + runTest(inputBuilder, false, + "ReportConfigSystemTest/30daysFromUntilDate/expected"); + } + + + /** + * System test with a specified until date and a {@link SinceDateArgumentType#FIRST_COMMIT_DATE_SHORTHAND} + * since date to capture from the first commit, using shallow cloning. + */ + @Test + public void testSinceBeginningDateRangeWithShallowCloning() { + InputBuilder inputBuilder = initInputBuilder() + .addSinceDate(SinceDateArgumentType.FIRST_COMMIT_DATE_SHORTHAND) + .addUntilDate("31/8/2024") + .addShallowCloning(); + + runTest(inputBuilder, true, + "ReportConfigSystemTest/sinceBeginningDateRangeWithShallowCloning/expected"); + } + + @Test + public void test30DaysFromUntilDateWithShallowCloning() { + InputBuilder inputBuilder = initInputBuilder() + .addUntilDate("31/8/2024") + .addShallowCloning(); + + runTest(inputBuilder, true, + "ReportConfigSystemTest/30daysFromUntilDateWithShallowCloning/expected"); + } + + /** + * System test with a specified until date and a {@link SinceDateArgumentType#FIRST_COMMIT_DATE_SHORTHAND} + * since date to capture from the first commit. + */ + @Test + public void testSinceBeginningDateRangeWithPortfolio() { + InputBuilder inputBuilder = initInputBuilder() + .addSinceDate(SinceDateArgumentType.FIRST_COMMIT_DATE_SHORTHAND) + .addUntilDate("31/8/2024") + .addPortfolio(); + + runTest(inputBuilder, false, + "ReportConfigSystemTest/sinceBeginningDateRangeWithPortfolio/expected"); + } + + + /** + * System test with a specified since date and until date, with the last modified date time in each + * line of code. + */ + @Test + public void testDateRangeWithModifiedDateTimeInLines() { + InputBuilder inputBuilder = initInputBuilder() + .addSinceDate("1/1/2024") + .addUntilDate("31/12/2024") + .addLastModifiedDateFlags(); + + runTest(inputBuilder, false, + "ReportConfigSystemTest/dateRangeWithModifiedDateTimeInLines/expected"); + } + + /** + * Returns a {@link InputBuilder} that is initialized with some default values. + *
Config Folder Path: {@code ReportConfigSystemTest} + *
Formats: {@link ReportConfigSystemTest#TESTING_FILE_FORMATS TESTING_FILE_FORMATS} + *
Timezone: {@link ReportConfigSystemTest#TEST_TIME_ZONE TEST_TIME_ZONE} + *
Output Folder Path: {@link ReportConfigSystemTest#OUTPUT_DIRECTORY OUTPUT_DIRECTORY} + *
Test Mode: {@code Enabled} + */ + private InputBuilder initInputBuilder() { + Path configFolder = loadResource(getClass(), "ReportConfigSystemTest"); + String formats = String.join(" ", TESTING_FILE_FORMATS); + + return new InputBuilder().addConfig(configFolder) + .addFormats(formats) + .addTimezone(TEST_TIME_ZONE) + .addOutput(OUTPUT_DIRECTORY); + } + + /** + * Generates the testing report and compares it with the expected report. + * Re-generates a normal report after the testing finished if the first report is shallow-cloned. + * + * @param inputBuilder The input builder that contains the command line input specified by user. + * @param shouldFreshClone Boolean for whether to clone repo again if it has been cloned before. + * @param pathToResource The location at which files generated during the test are stored. + */ + private void runTest(InputBuilder inputBuilder, boolean shouldFreshClone, String pathToResource) { + if (shouldFreshClone || didNotCloneRepoNormally) { + inputBuilder = inputBuilder.addFreshCloning(); + } + + RepoSense.main(translateCommandline(inputBuilder.build())); + + Path actualFiles = loadResource(getClass(), pathToResource); + SystemTestUtil.verifyReportJsonFiles(actualFiles, REPORT_DIRECTORY_PATH); + + didNotCloneRepoNormally = inputBuilder.isShallowCloning(); + } +} diff --git a/src/systemtest/resources/ConfigSystemTest/report-config.json b/src/systemtest/resources/ConfigSystemTest/report-config.json deleted file mode 100644 index c2aa7ed0bd..0000000000 --- a/src/systemtest/resources/ConfigSystemTest/report-config.json +++ /dev/null @@ -1 +0,0 @@ -{"title": "RepoSense Report Test Title"} diff --git a/src/systemtest/resources/ConfigSystemTest/report-config.yaml b/src/systemtest/resources/ConfigSystemTest/report-config.yaml new file mode 100644 index 0000000000..271619c6ba --- /dev/null +++ b/src/systemtest/resources/ConfigSystemTest/report-config.yaml @@ -0,0 +1 @@ +title: RepoSense Report Test Title diff --git a/src/systemtest/resources/ReportConfigSystemTest/30daysFromUntilDate/expected/reposense_publish-RepoSense_master/authorship.json b/src/systemtest/resources/ReportConfigSystemTest/30daysFromUntilDate/expected/reposense_publish-RepoSense_master/authorship.json new file mode 100644 index 0000000000..6e29968c55 --- /dev/null +++ b/src/systemtest/resources/ReportConfigSystemTest/30daysFromUntilDate/expected/reposense_publish-RepoSense_master/authorship.json @@ -0,0 +1 @@ +[{"path":"get-reposense.py","fileType":"other","lines":[{"lineNumber":1,"author":{"gitId":"-"},"content":"#!/usr/bin/env python","isFullCredit":false},{"lineNumber":2,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":3,"author":{"gitId":"-"},"content":"import argparse","isFullCredit":false},{"lineNumber":4,"author":{"gitId":"-"},"content":"import sys","isFullCredit":false},{"lineNumber":5,"author":{"gitId":"-"},"content":"import os","isFullCredit":false},{"lineNumber":6,"author":{"gitId":"-"},"content":"import shutil","isFullCredit":false},{"lineNumber":7,"author":{"gitId":"-"},"content":"import requests","isFullCredit":false},{"lineNumber":8,"author":{"gitId":"-"},"content":"import subprocess","isFullCredit":false},{"lineNumber":9,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":10,"author":{"gitId":"-"},"content":"JAR_FILENAME \u003d \u0027RepoSense.jar\u0027","isFullCredit":false},{"lineNumber":11,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":12,"author":{"gitId":"-"},"content":"def parse_args():","isFullCredit":false},{"lineNumber":13,"author":{"gitId":"-"},"content":" parser \u003d argparse.ArgumentParser(description\u003d\u0027Downloads a specific version of RepoSense.jar from our repository.\u0027)","isFullCredit":false},{"lineNumber":14,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":15,"author":{"gitId":"-"},"content":" group \u003d parser.add_mutually_exclusive_group()","isFullCredit":false},{"lineNumber":16,"author":{"gitId":"-"},"content":" group.add_argument(\u0027-r\u0027, \u0027--release\u0027, action\u003d\u0027store_true\u0027, help\u003d\u0027Get RepoSense.jar from the latest release (Stable)\u0027)","isFullCredit":false},{"lineNumber":17,"author":{"gitId":"-"},"content":" group.add_argument(\u0027-m\u0027, \u0027--master\u0027, action\u003d\u0027store_true\u0027, help\u003d\u0027Get RepoSense.jar from the latest master (Beta)\u0027)","isFullCredit":false},{"lineNumber":18,"author":{"gitId":"-"},"content":" group.add_argument(\u0027-t\u0027, \u0027--tag\u0027, help\u003d\u0027Get RepoSense.jar of a specific release version tag\u0027)","isFullCredit":false},{"lineNumber":19,"author":{"gitId":"jedkohjk"},"content":" group.add_argument(\u0027-l\u0027, \u0027--latest\u0027, help\u003d\u0027Get RepoSense.jar of the latest release of a specific version tag\u0027)","isFullCredit":false},{"lineNumber":20,"author":{"gitId":"-"},"content":" group.add_argument(\u0027-c\u0027, \u0027--commit\u0027, help\u003d\u0027Get RepoSense.jar of a specific commit\u0027)","isFullCredit":false},{"lineNumber":21,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":22,"author":{"gitId":"-"},"content":" parser.add_argument(\u0027-o\u0027, \u0027--overwrite\u0027, action\u003d\u0027store_true\u0027, help\u003d\u0027Overwrite RepoSense.jar file, if exists. Default: false\u0027)","isFullCredit":false},{"lineNumber":23,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":24,"author":{"gitId":"-"},"content":" return parser.parse_args()","isFullCredit":false},{"lineNumber":25,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":26,"author":{"gitId":"jedkohjk"},"content":"def handle_latest_tag(tag):","isFullCredit":false},{"lineNumber":27,"author":{"gitId":"jedkohjk"},"content":" page \u003d 1","isFullCredit":false},{"lineNumber":28,"author":{"gitId":"jedkohjk"},"content":" major \u003d tag.strip(\u0027. \u0027).split(\u0027.\u0027)","isFullCredit":false},{"lineNumber":29,"author":{"gitId":"jedkohjk"},"content":" while True:","isFullCredit":false},{"lineNumber":30,"author":{"gitId":"jedkohjk"},"content":" response \u003d requests.get(f\u0027https://api.github.com/repos/reposense/RepoSense/releases?per_page\u003d100\u0026page\u003d{page}\u0027)","isFullCredit":false},{"lineNumber":31,"author":{"gitId":"jedkohjk"},"content":" if response.status_code in [403, 500]:","isFullCredit":false},{"lineNumber":32,"author":{"gitId":"jedkohjk"},"content":" print(\u0027GitHub API has exceed the rate limit.\u0027)","isFullCredit":false},{"lineNumber":33,"author":{"gitId":"jedkohjk"},"content":" exit(1)","isFullCredit":false},{"lineNumber":34,"author":{"gitId":"jedkohjk"},"content":" releases \u003d response.json()","isFullCredit":false},{"lineNumber":35,"author":{"gitId":"jedkohjk"},"content":" if not releases:","isFullCredit":false},{"lineNumber":36,"author":{"gitId":"jedkohjk"},"content":" print(\u0027Error, the provided tag does not exist!\u0027)","isFullCredit":false},{"lineNumber":37,"author":{"gitId":"jedkohjk"},"content":" exit(1)","isFullCredit":false},{"lineNumber":38,"author":{"gitId":"jedkohjk"},"content":" for i in releases:","isFullCredit":false},{"lineNumber":39,"author":{"gitId":"jedkohjk"},"content":" release_tag \u003d i[\u0027tag_name\u0027]","isFullCredit":false},{"lineNumber":40,"author":{"gitId":"jedkohjk"},"content":" if release_tag.strip(\u0027. \u0027).split(\u0027.\u0027)[:len(major)] \u003d\u003d major:","isFullCredit":false},{"lineNumber":41,"author":{"gitId":"jedkohjk"},"content":" handle_specific_release(release_tag)","isFullCredit":false},{"lineNumber":42,"author":{"gitId":"jedkohjk"},"content":" exit()","isFullCredit":false},{"lineNumber":43,"author":{"gitId":"jedkohjk"},"content":" page +\u003d 1","isFullCredit":false},{"lineNumber":44,"author":{"gitId":"jedkohjk"},"content":"","isFullCredit":false},{"lineNumber":45,"author":{"gitId":"-"},"content":"def handle_specific_commit(commit):","isFullCredit":false},{"lineNumber":46,"author":{"gitId":"-"},"content":" get_reposense_jar(\u0027https://api.github.com/repos/reposense/RepoSense/commits/\u0027 + commit, commit\u003dcommit)","isFullCredit":false},{"lineNumber":47,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":48,"author":{"gitId":"-"},"content":"def handle_specific_release(tag):","isFullCredit":false},{"lineNumber":49,"author":{"gitId":"-"},"content":" get_reposense_jar(\u0027https://api.github.com/repos/reposense/RepoSense/releases/tags/\u0027 + tag, tag\u003dtag)","isFullCredit":false},{"lineNumber":50,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":51,"author":{"gitId":"-"},"content":"def handle_latest_release():","isFullCredit":false},{"lineNumber":52,"author":{"gitId":"-"},"content":" get_reposense_jar(\u0027https://api.github.com/repos/reposense/RepoSense/releases/latest\u0027)","isFullCredit":false},{"lineNumber":53,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":54,"author":{"gitId":"-"},"content":"def get_reposense_jar(url, tag\u003dNone, commit\u003dNone):","isFullCredit":false},{"lineNumber":55,"author":{"gitId":"-"},"content":" response \u003d requests.get(url)","isFullCredit":false},{"lineNumber":56,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":57,"author":{"gitId":"-"},"content":" if tag and response.status_code \u003d\u003d 404:","isFullCredit":false},{"lineNumber":58,"author":{"gitId":"-"},"content":" print(\u0027Error, the provided tag does not exist!\u0027)","isFullCredit":false},{"lineNumber":59,"author":{"gitId":"-"},"content":" exit(1)","isFullCredit":false},{"lineNumber":60,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":61,"author":{"gitId":"-"},"content":" if commit and response.status_code in [404, 422]:","isFullCredit":false},{"lineNumber":62,"author":{"gitId":"-"},"content":" print(\u0027Error, the provided commit does not exist!\u0027)","isFullCredit":false},{"lineNumber":63,"author":{"gitId":"-"},"content":" exit(1)","isFullCredit":false},{"lineNumber":64,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":65,"author":{"gitId":"-"},"content":" if response.status_code in [403, 500]:","isFullCredit":false},{"lineNumber":66,"author":{"gitId":"-"},"content":" print(\u0027GitHub API has exceed the rate limit. Falling back to alternative method...\u0027)","isFullCredit":false},{"lineNumber":67,"author":{"gitId":"-"},"content":" clone_and_make_reposense(tag\u003dtag, commit\u003dcommit)","isFullCredit":false},{"lineNumber":68,"author":{"gitId":"-"},"content":" return","isFullCredit":false},{"lineNumber":69,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":70,"author":{"gitId":"-"},"content":" if commit:","isFullCredit":false},{"lineNumber":71,"author":{"gitId":"-"},"content":" clone_and_make_reposense(commit\u003dcommit)","isFullCredit":false},{"lineNumber":72,"author":{"gitId":"-"},"content":" return","isFullCredit":false},{"lineNumber":73,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":74,"author":{"gitId":"-"},"content":" url \u003d response.json()[\u0027assets\u0027][0][\u0027browser_download_url\u0027]","isFullCredit":false},{"lineNumber":75,"author":{"gitId":"-"},"content":" download_file(url)","isFullCredit":false},{"lineNumber":76,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":77,"author":{"gitId":"-"},"content":"def clone_and_make_reposense(tag\u003dNone, commit\u003dNone):","isFullCredit":false},{"lineNumber":78,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":79,"author":{"gitId":"-"},"content":" # Cleanup cached RepoSense folder","isFullCredit":false},{"lineNumber":80,"author":{"gitId":"-"},"content":" shutil.rmtree(\u0027RepoSense\u0027, ignore_errors\u003dTrue)","isFullCredit":false},{"lineNumber":81,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":82,"author":{"gitId":"-"},"content":" command \u003d \\","isFullCredit":false},{"lineNumber":83,"author":{"gitId":"-"},"content":" \u0027\u0027\u0027","isFullCredit":false},{"lineNumber":84,"author":{"gitId":"-"},"content":" git clone \u0027https://github.com/reposense/RepoSense.git\u0027 \u0026\u0026","isFullCredit":false},{"lineNumber":85,"author":{"gitId":"-"},"content":" cd RepoSense \u0026\u0026","isFullCredit":false},{"lineNumber":86,"author":{"gitId":"-"},"content":" \u0027\u0027\u0027","isFullCredit":false},{"lineNumber":87,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":88,"author":{"gitId":"-"},"content":" if tag:","isFullCredit":false},{"lineNumber":89,"author":{"gitId":"-"},"content":" command +\u003d \u0027git checkout tags/{} -b deploy \u0026\u0026\u0027.format(tag)","isFullCredit":false},{"lineNumber":90,"author":{"gitId":"-"},"content":" elif commit:","isFullCredit":false},{"lineNumber":91,"author":{"gitId":"-"},"content":" command +\u003d \u0027git checkout {} -b deploy \u0026\u0026\u0027.format(commit)","isFullCredit":false},{"lineNumber":92,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":93,"author":{"gitId":"-"},"content":" command +\u003d \\","isFullCredit":false},{"lineNumber":94,"author":{"gitId":"-"},"content":" \u0027\u0027\u0027","isFullCredit":false},{"lineNumber":95,"author":{"gitId":"-"},"content":" ./gradlew zipreport shadowjar \u0026\u0026","isFullCredit":false},{"lineNumber":96,"author":{"gitId":"-"},"content":" mv build/jar/RepoSense.jar ../","isFullCredit":false},{"lineNumber":97,"author":{"gitId":"-"},"content":" \u0027\u0027\u0027","isFullCredit":false},{"lineNumber":98,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":99,"author":{"gitId":"-"},"content":" subprocess.check_call(command, shell\u003dTrue)","isFullCredit":false},{"lineNumber":100,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":101,"author":{"gitId":"-"},"content":"def download_file(url):","isFullCredit":false},{"lineNumber":102,"author":{"gitId":"-"},"content":" response \u003d requests.get(url, allow_redirects\u003dTrue)","isFullCredit":false},{"lineNumber":103,"author":{"gitId":"-"},"content":" open(JAR_FILENAME, \u0027wb\u0027).write(response.content)","isFullCredit":false},{"lineNumber":104,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":105,"author":{"gitId":"-"},"content":"if __name__ \u003d\u003d \"__main__\":","isFullCredit":false},{"lineNumber":106,"author":{"gitId":"-"},"content":" args \u003d parse_args()","isFullCredit":false},{"lineNumber":107,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":108,"author":{"gitId":"-"},"content":" if os.path.exists(JAR_FILENAME) and args.overwrite is False:","isFullCredit":false},{"lineNumber":109,"author":{"gitId":"-"},"content":" print(JAR_FILENAME + \u0027 already exists. Quitting.\u0027)","isFullCredit":false},{"lineNumber":110,"author":{"gitId":"-"},"content":" exit()","isFullCredit":false},{"lineNumber":111,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":112,"author":{"gitId":"-"},"content":" if args.tag:","isFullCredit":false},{"lineNumber":113,"author":{"gitId":"-"},"content":" handle_specific_release(args.tag)","isFullCredit":false},{"lineNumber":114,"author":{"gitId":"-"},"content":" exit()","isFullCredit":false},{"lineNumber":115,"author":{"gitId":"-"},"content":" ","isFullCredit":false},{"lineNumber":116,"author":{"gitId":"jedkohjk"},"content":" if args.latest:","isFullCredit":false},{"lineNumber":117,"author":{"gitId":"jedkohjk"},"content":" handle_latest_tag(args.latest)","isFullCredit":false},{"lineNumber":118,"author":{"gitId":"jedkohjk"},"content":" exit()","isFullCredit":false},{"lineNumber":119,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":120,"author":{"gitId":"-"},"content":" if args.commit:","isFullCredit":false},{"lineNumber":121,"author":{"gitId":"-"},"content":" handle_specific_commit(args.commit)","isFullCredit":false},{"lineNumber":122,"author":{"gitId":"-"},"content":" exit()","isFullCredit":false},{"lineNumber":123,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":124,"author":{"gitId":"-"},"content":" if args.master:","isFullCredit":false},{"lineNumber":125,"author":{"gitId":"-"},"content":" clone_and_make_reposense()","isFullCredit":false},{"lineNumber":126,"author":{"gitId":"-"},"content":" exit()","isFullCredit":false},{"lineNumber":127,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":128,"author":{"gitId":"-"},"content":" # If no arguments are provided or --release","isFullCredit":false},{"lineNumber":129,"author":{"gitId":"-"},"content":" handle_latest_release()","isFullCredit":false}],"authorContributionMap":{"jedkohjk":23,"-":106}},{"path":"run.sh","fileType":"other","lines":[{"lineNumber":1,"author":{"gitId":"-"},"content":"#!/bin/bash","isFullCredit":false},{"lineNumber":2,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":3,"author":{"gitId":"-"},"content":"# Downloads a specific version of RepoSense.jar of your choice from our repository","isFullCredit":false},{"lineNumber":4,"author":{"gitId":"-"},"content":"## Examples of supported options:","isFullCredit":false},{"lineNumber":5,"author":{"gitId":"-"},"content":"### ./get-reposense.py --release # Gets the latest release (Stable)","isFullCredit":false},{"lineNumber":6,"author":{"gitId":"-"},"content":"### ./get-reposense.py --master # Gets the latest master (Beta)","isFullCredit":false},{"lineNumber":7,"author":{"gitId":"-"},"content":"### ./get-reposense.py --tag v1.6.1 # Gets a specific version","isFullCredit":false},{"lineNumber":8,"author":{"gitId":"jedkohjk"},"content":"### ./get-reposense.py --latest v1.6 # Gets the latest version with the given tag prefix e.g. v1.6.1","isFullCredit":false},{"lineNumber":9,"author":{"gitId":"-"},"content":"### ./get-reposense.py --commit abc123 # Gets a specific commit","isFullCredit":false},{"lineNumber":10,"author":{"gitId":"-"},"content":"### ./get-reposense.py --release --overwrite # Overwrite RepoSense.jar, if exists, with the latest release","isFullCredit":false},{"lineNumber":11,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":12,"author":{"gitId":"-"},"content":"./get-reposense.py --release","isFullCredit":false},{"lineNumber":13,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":14,"author":{"gitId":"-"},"content":"# Executes RepoSense","isFullCredit":false},{"lineNumber":15,"author":{"gitId":"-"},"content":"# Do not change the default output folder name (reposense-report)","isFullCredit":false},{"lineNumber":16,"author":{"gitId":"-"},"content":"## Examples of other valid options; For more, please view the user guide","isFullCredit":false},{"lineNumber":17,"author":{"gitId":"-"},"content":"### java -jar RepoSense.jar --repos https://github.com/reposense/RepoSense.git","isFullCredit":false},{"lineNumber":18,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":19,"author":{"gitId":"-"},"content":"java -jar RepoSense.jar --config ./configs","isFullCredit":false}],"authorContributionMap":{"jedkohjk":1,"-":18}}] diff --git a/src/systemtest/resources/ReportConfigSystemTest/30daysFromUntilDate/expected/reposense_publish-RepoSense_master/commits.json b/src/systemtest/resources/ReportConfigSystemTest/30daysFromUntilDate/expected/reposense_publish-RepoSense_master/commits.json new file mode 100644 index 0000000000..5c4f422026 --- /dev/null +++ b/src/systemtest/resources/ReportConfigSystemTest/30daysFromUntilDate/expected/reposense_publish-RepoSense_master/commits.json @@ -0,0 +1 @@ +{"authorDailyContributionsMap":{"jedkohjk":[{"date":"2024-08-02T00:00:00","commitResults":[{"hash":"80185806433b561004c3d0245997a77afcc674f3","isMergeCommit":false,"messageTitle":"Add flag to get the latest release from a specified major version (#12)","messageBody":"The `--tag` flag fetches the exact specified RepoSense version, but provides no way to fetch the latest release of a specified major version.\r\n\r\nLet\u0027s introduce the `--latest` or `-l` flag to get the latest release from a specified major version.","fileTypesAndContributionMap":{"other":{"insertions":25,"deletions":0}}}]},{"date":"2024-08-13T00:00:00","commitResults":[{"hash":"3a748c5843b273dafa3080956eb138093b4b58c9","isMergeCommit":false,"messageTitle":"Clarify description of --latest flag in run.sh (#13)","messageBody":"Information about the function of the `--latest` flag is unclear.\r\n\r\nLet\u0027s clarify the description of `--latest` flag in `run.sh`.\r\n","fileTypesAndContributionMap":{"other":{"insertions":1,"deletions":1}}}]}]},"authorFileTypeContributionMap":{"jedkohjk":{"code":0,"tests":0,"docs":0,"other":24}},"authorContributionVariance":{"jedkohjk":41.209164},"authorDisplayNameMap":{"jedkohjk":"jedkohjk"}} diff --git a/src/systemtest/resources/ReportConfigSystemTest/30daysFromUntilDate/expected/summary.json b/src/systemtest/resources/ReportConfigSystemTest/30daysFromUntilDate/expected/summary.json new file mode 100644 index 0000000000..e84da20e0b --- /dev/null +++ b/src/systemtest/resources/ReportConfigSystemTest/30daysFromUntilDate/expected/summary.json @@ -0,0 +1 @@ +{"reportGeneratedTime":"Wed, 9 Apr 2025 15:46:34 SGT","reportGenerationTime":" 1.74 second(s)","zoneId":"Asia/Singapore","reportTitle":"RepoSense Report","repos":[{"location":{"location":"https://github.com/reposense/publish-RepoSense.git","repoName":"publish-RepoSense","organization":"reposense","domainName":"github"},"branch":"master","displayName":"reposense/publish-RepoSense[master]","outputFolderName":"reposense_publish-RepoSense_master","sinceDate":"2024-07-31T00:00:00","untilDate":"2024-08-31T23:59:59"}],"errorSet":[],"sinceDate":"2024-07-31T00:00:00","untilDate":"2024-08-31T23:59:59","isSinceDateProvided":false,"isUntilDateProvided":true,"supportedDomainUrlMap":{"NOT_RECOGNIZED":{"BRANCH":"","REPO_URL":"UNSUPPORTED","BASE_URL":"UNSUPPORTED","HISTORY_PATH":"","COMMIT_PATH":"","BLAME_PATH":""},"github":{"BRANCH":"tree/$BRANCH","REPO_URL":"https://github.com/$ORGANIZATION/$REPO_NAME/","BASE_URL":"https://github.com/","HISTORY_PATH":"commits/$BRANCH/$FILE_PATH","COMMIT_PATH":"commit/$COMMIT_HASH","BLAME_PATH":"blame/$BRANCH/$FILE_PATH"}},"isAuthorshipAnalyzed":false,"repoBlurbs":{"blurbMap":{"https://github.com/reposense/publish-RepoSense/tree/master":"Publish branch of Reposense"}},"authorBlurbs":{"blurbMap":{}},"isPortfolio":false} diff --git a/src/systemtest/resources/ReportConfigSystemTest/30daysFromUntilDateWithShallowCloning/expected/reposense_publish-RepoSense_master/authorship.json b/src/systemtest/resources/ReportConfigSystemTest/30daysFromUntilDateWithShallowCloning/expected/reposense_publish-RepoSense_master/authorship.json new file mode 100644 index 0000000000..6e29968c55 --- /dev/null +++ b/src/systemtest/resources/ReportConfigSystemTest/30daysFromUntilDateWithShallowCloning/expected/reposense_publish-RepoSense_master/authorship.json @@ -0,0 +1 @@ +[{"path":"get-reposense.py","fileType":"other","lines":[{"lineNumber":1,"author":{"gitId":"-"},"content":"#!/usr/bin/env python","isFullCredit":false},{"lineNumber":2,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":3,"author":{"gitId":"-"},"content":"import argparse","isFullCredit":false},{"lineNumber":4,"author":{"gitId":"-"},"content":"import sys","isFullCredit":false},{"lineNumber":5,"author":{"gitId":"-"},"content":"import os","isFullCredit":false},{"lineNumber":6,"author":{"gitId":"-"},"content":"import shutil","isFullCredit":false},{"lineNumber":7,"author":{"gitId":"-"},"content":"import requests","isFullCredit":false},{"lineNumber":8,"author":{"gitId":"-"},"content":"import subprocess","isFullCredit":false},{"lineNumber":9,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":10,"author":{"gitId":"-"},"content":"JAR_FILENAME \u003d \u0027RepoSense.jar\u0027","isFullCredit":false},{"lineNumber":11,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":12,"author":{"gitId":"-"},"content":"def parse_args():","isFullCredit":false},{"lineNumber":13,"author":{"gitId":"-"},"content":" parser \u003d argparse.ArgumentParser(description\u003d\u0027Downloads a specific version of RepoSense.jar from our repository.\u0027)","isFullCredit":false},{"lineNumber":14,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":15,"author":{"gitId":"-"},"content":" group \u003d parser.add_mutually_exclusive_group()","isFullCredit":false},{"lineNumber":16,"author":{"gitId":"-"},"content":" group.add_argument(\u0027-r\u0027, \u0027--release\u0027, action\u003d\u0027store_true\u0027, help\u003d\u0027Get RepoSense.jar from the latest release (Stable)\u0027)","isFullCredit":false},{"lineNumber":17,"author":{"gitId":"-"},"content":" group.add_argument(\u0027-m\u0027, \u0027--master\u0027, action\u003d\u0027store_true\u0027, help\u003d\u0027Get RepoSense.jar from the latest master (Beta)\u0027)","isFullCredit":false},{"lineNumber":18,"author":{"gitId":"-"},"content":" group.add_argument(\u0027-t\u0027, \u0027--tag\u0027, help\u003d\u0027Get RepoSense.jar of a specific release version tag\u0027)","isFullCredit":false},{"lineNumber":19,"author":{"gitId":"jedkohjk"},"content":" group.add_argument(\u0027-l\u0027, \u0027--latest\u0027, help\u003d\u0027Get RepoSense.jar of the latest release of a specific version tag\u0027)","isFullCredit":false},{"lineNumber":20,"author":{"gitId":"-"},"content":" group.add_argument(\u0027-c\u0027, \u0027--commit\u0027, help\u003d\u0027Get RepoSense.jar of a specific commit\u0027)","isFullCredit":false},{"lineNumber":21,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":22,"author":{"gitId":"-"},"content":" parser.add_argument(\u0027-o\u0027, \u0027--overwrite\u0027, action\u003d\u0027store_true\u0027, help\u003d\u0027Overwrite RepoSense.jar file, if exists. Default: false\u0027)","isFullCredit":false},{"lineNumber":23,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":24,"author":{"gitId":"-"},"content":" return parser.parse_args()","isFullCredit":false},{"lineNumber":25,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":26,"author":{"gitId":"jedkohjk"},"content":"def handle_latest_tag(tag):","isFullCredit":false},{"lineNumber":27,"author":{"gitId":"jedkohjk"},"content":" page \u003d 1","isFullCredit":false},{"lineNumber":28,"author":{"gitId":"jedkohjk"},"content":" major \u003d tag.strip(\u0027. \u0027).split(\u0027.\u0027)","isFullCredit":false},{"lineNumber":29,"author":{"gitId":"jedkohjk"},"content":" while True:","isFullCredit":false},{"lineNumber":30,"author":{"gitId":"jedkohjk"},"content":" response \u003d requests.get(f\u0027https://api.github.com/repos/reposense/RepoSense/releases?per_page\u003d100\u0026page\u003d{page}\u0027)","isFullCredit":false},{"lineNumber":31,"author":{"gitId":"jedkohjk"},"content":" if response.status_code in [403, 500]:","isFullCredit":false},{"lineNumber":32,"author":{"gitId":"jedkohjk"},"content":" print(\u0027GitHub API has exceed the rate limit.\u0027)","isFullCredit":false},{"lineNumber":33,"author":{"gitId":"jedkohjk"},"content":" exit(1)","isFullCredit":false},{"lineNumber":34,"author":{"gitId":"jedkohjk"},"content":" releases \u003d response.json()","isFullCredit":false},{"lineNumber":35,"author":{"gitId":"jedkohjk"},"content":" if not releases:","isFullCredit":false},{"lineNumber":36,"author":{"gitId":"jedkohjk"},"content":" print(\u0027Error, the provided tag does not exist!\u0027)","isFullCredit":false},{"lineNumber":37,"author":{"gitId":"jedkohjk"},"content":" exit(1)","isFullCredit":false},{"lineNumber":38,"author":{"gitId":"jedkohjk"},"content":" for i in releases:","isFullCredit":false},{"lineNumber":39,"author":{"gitId":"jedkohjk"},"content":" release_tag \u003d i[\u0027tag_name\u0027]","isFullCredit":false},{"lineNumber":40,"author":{"gitId":"jedkohjk"},"content":" if release_tag.strip(\u0027. \u0027).split(\u0027.\u0027)[:len(major)] \u003d\u003d major:","isFullCredit":false},{"lineNumber":41,"author":{"gitId":"jedkohjk"},"content":" handle_specific_release(release_tag)","isFullCredit":false},{"lineNumber":42,"author":{"gitId":"jedkohjk"},"content":" exit()","isFullCredit":false},{"lineNumber":43,"author":{"gitId":"jedkohjk"},"content":" page +\u003d 1","isFullCredit":false},{"lineNumber":44,"author":{"gitId":"jedkohjk"},"content":"","isFullCredit":false},{"lineNumber":45,"author":{"gitId":"-"},"content":"def handle_specific_commit(commit):","isFullCredit":false},{"lineNumber":46,"author":{"gitId":"-"},"content":" get_reposense_jar(\u0027https://api.github.com/repos/reposense/RepoSense/commits/\u0027 + commit, commit\u003dcommit)","isFullCredit":false},{"lineNumber":47,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":48,"author":{"gitId":"-"},"content":"def handle_specific_release(tag):","isFullCredit":false},{"lineNumber":49,"author":{"gitId":"-"},"content":" get_reposense_jar(\u0027https://api.github.com/repos/reposense/RepoSense/releases/tags/\u0027 + tag, tag\u003dtag)","isFullCredit":false},{"lineNumber":50,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":51,"author":{"gitId":"-"},"content":"def handle_latest_release():","isFullCredit":false},{"lineNumber":52,"author":{"gitId":"-"},"content":" get_reposense_jar(\u0027https://api.github.com/repos/reposense/RepoSense/releases/latest\u0027)","isFullCredit":false},{"lineNumber":53,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":54,"author":{"gitId":"-"},"content":"def get_reposense_jar(url, tag\u003dNone, commit\u003dNone):","isFullCredit":false},{"lineNumber":55,"author":{"gitId":"-"},"content":" response \u003d requests.get(url)","isFullCredit":false},{"lineNumber":56,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":57,"author":{"gitId":"-"},"content":" if tag and response.status_code \u003d\u003d 404:","isFullCredit":false},{"lineNumber":58,"author":{"gitId":"-"},"content":" print(\u0027Error, the provided tag does not exist!\u0027)","isFullCredit":false},{"lineNumber":59,"author":{"gitId":"-"},"content":" exit(1)","isFullCredit":false},{"lineNumber":60,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":61,"author":{"gitId":"-"},"content":" if commit and response.status_code in [404, 422]:","isFullCredit":false},{"lineNumber":62,"author":{"gitId":"-"},"content":" print(\u0027Error, the provided commit does not exist!\u0027)","isFullCredit":false},{"lineNumber":63,"author":{"gitId":"-"},"content":" exit(1)","isFullCredit":false},{"lineNumber":64,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":65,"author":{"gitId":"-"},"content":" if response.status_code in [403, 500]:","isFullCredit":false},{"lineNumber":66,"author":{"gitId":"-"},"content":" print(\u0027GitHub API has exceed the rate limit. Falling back to alternative method...\u0027)","isFullCredit":false},{"lineNumber":67,"author":{"gitId":"-"},"content":" clone_and_make_reposense(tag\u003dtag, commit\u003dcommit)","isFullCredit":false},{"lineNumber":68,"author":{"gitId":"-"},"content":" return","isFullCredit":false},{"lineNumber":69,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":70,"author":{"gitId":"-"},"content":" if commit:","isFullCredit":false},{"lineNumber":71,"author":{"gitId":"-"},"content":" clone_and_make_reposense(commit\u003dcommit)","isFullCredit":false},{"lineNumber":72,"author":{"gitId":"-"},"content":" return","isFullCredit":false},{"lineNumber":73,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":74,"author":{"gitId":"-"},"content":" url \u003d response.json()[\u0027assets\u0027][0][\u0027browser_download_url\u0027]","isFullCredit":false},{"lineNumber":75,"author":{"gitId":"-"},"content":" download_file(url)","isFullCredit":false},{"lineNumber":76,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":77,"author":{"gitId":"-"},"content":"def clone_and_make_reposense(tag\u003dNone, commit\u003dNone):","isFullCredit":false},{"lineNumber":78,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":79,"author":{"gitId":"-"},"content":" # Cleanup cached RepoSense folder","isFullCredit":false},{"lineNumber":80,"author":{"gitId":"-"},"content":" shutil.rmtree(\u0027RepoSense\u0027, ignore_errors\u003dTrue)","isFullCredit":false},{"lineNumber":81,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":82,"author":{"gitId":"-"},"content":" command \u003d \\","isFullCredit":false},{"lineNumber":83,"author":{"gitId":"-"},"content":" \u0027\u0027\u0027","isFullCredit":false},{"lineNumber":84,"author":{"gitId":"-"},"content":" git clone \u0027https://github.com/reposense/RepoSense.git\u0027 \u0026\u0026","isFullCredit":false},{"lineNumber":85,"author":{"gitId":"-"},"content":" cd RepoSense \u0026\u0026","isFullCredit":false},{"lineNumber":86,"author":{"gitId":"-"},"content":" \u0027\u0027\u0027","isFullCredit":false},{"lineNumber":87,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":88,"author":{"gitId":"-"},"content":" if tag:","isFullCredit":false},{"lineNumber":89,"author":{"gitId":"-"},"content":" command +\u003d \u0027git checkout tags/{} -b deploy \u0026\u0026\u0027.format(tag)","isFullCredit":false},{"lineNumber":90,"author":{"gitId":"-"},"content":" elif commit:","isFullCredit":false},{"lineNumber":91,"author":{"gitId":"-"},"content":" command +\u003d \u0027git checkout {} -b deploy \u0026\u0026\u0027.format(commit)","isFullCredit":false},{"lineNumber":92,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":93,"author":{"gitId":"-"},"content":" command +\u003d \\","isFullCredit":false},{"lineNumber":94,"author":{"gitId":"-"},"content":" \u0027\u0027\u0027","isFullCredit":false},{"lineNumber":95,"author":{"gitId":"-"},"content":" ./gradlew zipreport shadowjar \u0026\u0026","isFullCredit":false},{"lineNumber":96,"author":{"gitId":"-"},"content":" mv build/jar/RepoSense.jar ../","isFullCredit":false},{"lineNumber":97,"author":{"gitId":"-"},"content":" \u0027\u0027\u0027","isFullCredit":false},{"lineNumber":98,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":99,"author":{"gitId":"-"},"content":" subprocess.check_call(command, shell\u003dTrue)","isFullCredit":false},{"lineNumber":100,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":101,"author":{"gitId":"-"},"content":"def download_file(url):","isFullCredit":false},{"lineNumber":102,"author":{"gitId":"-"},"content":" response \u003d requests.get(url, allow_redirects\u003dTrue)","isFullCredit":false},{"lineNumber":103,"author":{"gitId":"-"},"content":" open(JAR_FILENAME, \u0027wb\u0027).write(response.content)","isFullCredit":false},{"lineNumber":104,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":105,"author":{"gitId":"-"},"content":"if __name__ \u003d\u003d \"__main__\":","isFullCredit":false},{"lineNumber":106,"author":{"gitId":"-"},"content":" args \u003d parse_args()","isFullCredit":false},{"lineNumber":107,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":108,"author":{"gitId":"-"},"content":" if os.path.exists(JAR_FILENAME) and args.overwrite is False:","isFullCredit":false},{"lineNumber":109,"author":{"gitId":"-"},"content":" print(JAR_FILENAME + \u0027 already exists. Quitting.\u0027)","isFullCredit":false},{"lineNumber":110,"author":{"gitId":"-"},"content":" exit()","isFullCredit":false},{"lineNumber":111,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":112,"author":{"gitId":"-"},"content":" if args.tag:","isFullCredit":false},{"lineNumber":113,"author":{"gitId":"-"},"content":" handle_specific_release(args.tag)","isFullCredit":false},{"lineNumber":114,"author":{"gitId":"-"},"content":" exit()","isFullCredit":false},{"lineNumber":115,"author":{"gitId":"-"},"content":" ","isFullCredit":false},{"lineNumber":116,"author":{"gitId":"jedkohjk"},"content":" if args.latest:","isFullCredit":false},{"lineNumber":117,"author":{"gitId":"jedkohjk"},"content":" handle_latest_tag(args.latest)","isFullCredit":false},{"lineNumber":118,"author":{"gitId":"jedkohjk"},"content":" exit()","isFullCredit":false},{"lineNumber":119,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":120,"author":{"gitId":"-"},"content":" if args.commit:","isFullCredit":false},{"lineNumber":121,"author":{"gitId":"-"},"content":" handle_specific_commit(args.commit)","isFullCredit":false},{"lineNumber":122,"author":{"gitId":"-"},"content":" exit()","isFullCredit":false},{"lineNumber":123,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":124,"author":{"gitId":"-"},"content":" if args.master:","isFullCredit":false},{"lineNumber":125,"author":{"gitId":"-"},"content":" clone_and_make_reposense()","isFullCredit":false},{"lineNumber":126,"author":{"gitId":"-"},"content":" exit()","isFullCredit":false},{"lineNumber":127,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":128,"author":{"gitId":"-"},"content":" # If no arguments are provided or --release","isFullCredit":false},{"lineNumber":129,"author":{"gitId":"-"},"content":" handle_latest_release()","isFullCredit":false}],"authorContributionMap":{"jedkohjk":23,"-":106}},{"path":"run.sh","fileType":"other","lines":[{"lineNumber":1,"author":{"gitId":"-"},"content":"#!/bin/bash","isFullCredit":false},{"lineNumber":2,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":3,"author":{"gitId":"-"},"content":"# Downloads a specific version of RepoSense.jar of your choice from our repository","isFullCredit":false},{"lineNumber":4,"author":{"gitId":"-"},"content":"## Examples of supported options:","isFullCredit":false},{"lineNumber":5,"author":{"gitId":"-"},"content":"### ./get-reposense.py --release # Gets the latest release (Stable)","isFullCredit":false},{"lineNumber":6,"author":{"gitId":"-"},"content":"### ./get-reposense.py --master # Gets the latest master (Beta)","isFullCredit":false},{"lineNumber":7,"author":{"gitId":"-"},"content":"### ./get-reposense.py --tag v1.6.1 # Gets a specific version","isFullCredit":false},{"lineNumber":8,"author":{"gitId":"jedkohjk"},"content":"### ./get-reposense.py --latest v1.6 # Gets the latest version with the given tag prefix e.g. v1.6.1","isFullCredit":false},{"lineNumber":9,"author":{"gitId":"-"},"content":"### ./get-reposense.py --commit abc123 # Gets a specific commit","isFullCredit":false},{"lineNumber":10,"author":{"gitId":"-"},"content":"### ./get-reposense.py --release --overwrite # Overwrite RepoSense.jar, if exists, with the latest release","isFullCredit":false},{"lineNumber":11,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":12,"author":{"gitId":"-"},"content":"./get-reposense.py --release","isFullCredit":false},{"lineNumber":13,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":14,"author":{"gitId":"-"},"content":"# Executes RepoSense","isFullCredit":false},{"lineNumber":15,"author":{"gitId":"-"},"content":"# Do not change the default output folder name (reposense-report)","isFullCredit":false},{"lineNumber":16,"author":{"gitId":"-"},"content":"## Examples of other valid options; For more, please view the user guide","isFullCredit":false},{"lineNumber":17,"author":{"gitId":"-"},"content":"### java -jar RepoSense.jar --repos https://github.com/reposense/RepoSense.git","isFullCredit":false},{"lineNumber":18,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":19,"author":{"gitId":"-"},"content":"java -jar RepoSense.jar --config ./configs","isFullCredit":false}],"authorContributionMap":{"jedkohjk":1,"-":18}}] diff --git a/src/systemtest/resources/ReportConfigSystemTest/30daysFromUntilDateWithShallowCloning/expected/reposense_publish-RepoSense_master/commits.json b/src/systemtest/resources/ReportConfigSystemTest/30daysFromUntilDateWithShallowCloning/expected/reposense_publish-RepoSense_master/commits.json new file mode 100644 index 0000000000..5c4f422026 --- /dev/null +++ b/src/systemtest/resources/ReportConfigSystemTest/30daysFromUntilDateWithShallowCloning/expected/reposense_publish-RepoSense_master/commits.json @@ -0,0 +1 @@ +{"authorDailyContributionsMap":{"jedkohjk":[{"date":"2024-08-02T00:00:00","commitResults":[{"hash":"80185806433b561004c3d0245997a77afcc674f3","isMergeCommit":false,"messageTitle":"Add flag to get the latest release from a specified major version (#12)","messageBody":"The `--tag` flag fetches the exact specified RepoSense version, but provides no way to fetch the latest release of a specified major version.\r\n\r\nLet\u0027s introduce the `--latest` or `-l` flag to get the latest release from a specified major version.","fileTypesAndContributionMap":{"other":{"insertions":25,"deletions":0}}}]},{"date":"2024-08-13T00:00:00","commitResults":[{"hash":"3a748c5843b273dafa3080956eb138093b4b58c9","isMergeCommit":false,"messageTitle":"Clarify description of --latest flag in run.sh (#13)","messageBody":"Information about the function of the `--latest` flag is unclear.\r\n\r\nLet\u0027s clarify the description of `--latest` flag in `run.sh`.\r\n","fileTypesAndContributionMap":{"other":{"insertions":1,"deletions":1}}}]}]},"authorFileTypeContributionMap":{"jedkohjk":{"code":0,"tests":0,"docs":0,"other":24}},"authorContributionVariance":{"jedkohjk":41.209164},"authorDisplayNameMap":{"jedkohjk":"jedkohjk"}} diff --git a/src/systemtest/resources/ReportConfigSystemTest/30daysFromUntilDateWithShallowCloning/expected/summary.json b/src/systemtest/resources/ReportConfigSystemTest/30daysFromUntilDateWithShallowCloning/expected/summary.json new file mode 100644 index 0000000000..7dc0ab07a0 --- /dev/null +++ b/src/systemtest/resources/ReportConfigSystemTest/30daysFromUntilDateWithShallowCloning/expected/summary.json @@ -0,0 +1 @@ +{"reportGeneratedTime":"Wed, 9 Apr 2025 15:57:59 SGT","reportGenerationTime":" 4.00 second(s)","zoneId":"Asia/Singapore","reportTitle":"RepoSense Report","repos":[{"location":{"location":"https://github.com/reposense/publish-RepoSense.git","repoName":"publish-RepoSense","organization":"reposense","domainName":"github"},"branch":"master","displayName":"reposense/publish-RepoSense[master]","outputFolderName":"reposense_publish-RepoSense_master","sinceDate":"2024-07-31T00:00:00","untilDate":"2024-08-31T23:59:59"}],"errorSet":[],"sinceDate":"2024-07-31T00:00:00","untilDate":"2024-08-31T23:59:59","isSinceDateProvided":false,"isUntilDateProvided":true,"supportedDomainUrlMap":{"NOT_RECOGNIZED":{"BRANCH":"","REPO_URL":"UNSUPPORTED","BASE_URL":"UNSUPPORTED","HISTORY_PATH":"","COMMIT_PATH":"","BLAME_PATH":""},"github":{"BRANCH":"tree/$BRANCH","REPO_URL":"https://github.com/$ORGANIZATION/$REPO_NAME/","BASE_URL":"https://github.com/","HISTORY_PATH":"commits/$BRANCH/$FILE_PATH","COMMIT_PATH":"commit/$COMMIT_HASH","BLAME_PATH":"blame/$BRANCH/$FILE_PATH"}},"isAuthorshipAnalyzed":false,"repoBlurbs":{"blurbMap":{"https://github.com/reposense/publish-RepoSense/tree/master":"Publish branch of Reposense"}},"authorBlurbs":{"blurbMap":{}},"isPortfolio":false} diff --git a/src/systemtest/resources/ReportConfigSystemTest/dateRangeWithModifiedDateTimeInLines/expected/reposense_publish-RepoSense_master/authorship.json b/src/systemtest/resources/ReportConfigSystemTest/dateRangeWithModifiedDateTimeInLines/expected/reposense_publish-RepoSense_master/authorship.json new file mode 100644 index 0000000000..3ac1ac7878 --- /dev/null +++ b/src/systemtest/resources/ReportConfigSystemTest/dateRangeWithModifiedDateTimeInLines/expected/reposense_publish-RepoSense_master/authorship.json @@ -0,0 +1 @@ +[{"path":"get-reposense.py","fileType":"other","lines":[{"lineNumber":1,"author":{"gitId":"-"},"content":"#!/usr/bin/env python","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":2,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":3,"author":{"gitId":"-"},"content":"import argparse","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":4,"author":{"gitId":"-"},"content":"import sys","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":5,"author":{"gitId":"-"},"content":"import os","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":6,"author":{"gitId":"-"},"content":"import shutil","lastModifiedDate":"2019-01-26T21:42:39","isFullCredit":false},{"lineNumber":7,"author":{"gitId":"-"},"content":"import requests","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":8,"author":{"gitId":"-"},"content":"import subprocess","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":9,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":10,"author":{"gitId":"-"},"content":"JAR_FILENAME \u003d \u0027RepoSense.jar\u0027","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":11,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":12,"author":{"gitId":"-"},"content":"def parse_args():","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":13,"author":{"gitId":"-"},"content":" parser \u003d argparse.ArgumentParser(description\u003d\u0027Downloads a specific version of RepoSense.jar from our repository.\u0027)","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":14,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":15,"author":{"gitId":"-"},"content":" group \u003d parser.add_mutually_exclusive_group()","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":16,"author":{"gitId":"-"},"content":" group.add_argument(\u0027-r\u0027, \u0027--release\u0027, action\u003d\u0027store_true\u0027, help\u003d\u0027Get RepoSense.jar from the latest release (Stable)\u0027)","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":17,"author":{"gitId":"-"},"content":" group.add_argument(\u0027-m\u0027, \u0027--master\u0027, action\u003d\u0027store_true\u0027, help\u003d\u0027Get RepoSense.jar from the latest master (Beta)\u0027)","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":18,"author":{"gitId":"-"},"content":" group.add_argument(\u0027-t\u0027, \u0027--tag\u0027, help\u003d\u0027Get RepoSense.jar of a specific release version tag\u0027)","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":19,"author":{"gitId":"jedkohjk"},"content":" group.add_argument(\u0027-l\u0027, \u0027--latest\u0027, help\u003d\u0027Get RepoSense.jar of the latest release of a specific version tag\u0027)","lastModifiedDate":"2024-08-02T00:19:00","isFullCredit":false},{"lineNumber":20,"author":{"gitId":"-"},"content":" group.add_argument(\u0027-c\u0027, \u0027--commit\u0027, help\u003d\u0027Get RepoSense.jar of a specific commit\u0027)","lastModifiedDate":"2021-03-31T17:56:18","isFullCredit":false},{"lineNumber":21,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":22,"author":{"gitId":"-"},"content":" parser.add_argument(\u0027-o\u0027, \u0027--overwrite\u0027, action\u003d\u0027store_true\u0027, help\u003d\u0027Overwrite RepoSense.jar file, if exists. Default: false\u0027)","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":23,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":24,"author":{"gitId":"-"},"content":" return parser.parse_args()","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":25,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":26,"author":{"gitId":"jedkohjk"},"content":"def handle_latest_tag(tag):","lastModifiedDate":"2024-08-02T00:19:00","isFullCredit":false},{"lineNumber":27,"author":{"gitId":"jedkohjk"},"content":" page \u003d 1","lastModifiedDate":"2024-08-02T00:19:00","isFullCredit":false},{"lineNumber":28,"author":{"gitId":"jedkohjk"},"content":" major \u003d tag.strip(\u0027. \u0027).split(\u0027.\u0027)","lastModifiedDate":"2024-08-02T00:19:00","isFullCredit":false},{"lineNumber":29,"author":{"gitId":"jedkohjk"},"content":" while True:","lastModifiedDate":"2024-08-02T00:19:00","isFullCredit":false},{"lineNumber":30,"author":{"gitId":"jedkohjk"},"content":" response \u003d requests.get(f\u0027https://api.github.com/repos/reposense/RepoSense/releases?per_page\u003d100\u0026page\u003d{page}\u0027)","lastModifiedDate":"2024-08-02T00:19:00","isFullCredit":false},{"lineNumber":31,"author":{"gitId":"jedkohjk"},"content":" if response.status_code in [403, 500]:","lastModifiedDate":"2024-08-02T00:19:00","isFullCredit":false},{"lineNumber":32,"author":{"gitId":"jedkohjk"},"content":" print(\u0027GitHub API has exceed the rate limit.\u0027)","lastModifiedDate":"2024-08-02T00:19:00","isFullCredit":false},{"lineNumber":33,"author":{"gitId":"jedkohjk"},"content":" exit(1)","lastModifiedDate":"2024-08-02T00:19:00","isFullCredit":false},{"lineNumber":34,"author":{"gitId":"jedkohjk"},"content":" releases \u003d response.json()","lastModifiedDate":"2024-08-02T00:19:00","isFullCredit":false},{"lineNumber":35,"author":{"gitId":"jedkohjk"},"content":" if not releases:","lastModifiedDate":"2024-08-02T00:19:00","isFullCredit":false},{"lineNumber":36,"author":{"gitId":"jedkohjk"},"content":" print(\u0027Error, the provided tag does not exist!\u0027)","lastModifiedDate":"2024-08-02T00:19:00","isFullCredit":false},{"lineNumber":37,"author":{"gitId":"jedkohjk"},"content":" exit(1)","lastModifiedDate":"2024-08-02T00:19:00","isFullCredit":false},{"lineNumber":38,"author":{"gitId":"jedkohjk"},"content":" for i in releases:","lastModifiedDate":"2024-08-02T00:19:00","isFullCredit":false},{"lineNumber":39,"author":{"gitId":"jedkohjk"},"content":" release_tag \u003d i[\u0027tag_name\u0027]","lastModifiedDate":"2024-08-02T00:19:00","isFullCredit":false},{"lineNumber":40,"author":{"gitId":"jedkohjk"},"content":" if release_tag.strip(\u0027. \u0027).split(\u0027.\u0027)[:len(major)] \u003d\u003d major:","lastModifiedDate":"2024-08-02T00:19:00","isFullCredit":false},{"lineNumber":41,"author":{"gitId":"jedkohjk"},"content":" handle_specific_release(release_tag)","lastModifiedDate":"2024-08-02T00:19:00","isFullCredit":false},{"lineNumber":42,"author":{"gitId":"jedkohjk"},"content":" exit()","lastModifiedDate":"2024-08-02T00:19:00","isFullCredit":false},{"lineNumber":43,"author":{"gitId":"jedkohjk"},"content":" page +\u003d 1","lastModifiedDate":"2024-08-02T00:19:00","isFullCredit":false},{"lineNumber":44,"author":{"gitId":"jedkohjk"},"content":"","lastModifiedDate":"2024-08-02T00:19:00","isFullCredit":false},{"lineNumber":45,"author":{"gitId":"-"},"content":"def handle_specific_commit(commit):","lastModifiedDate":"2021-03-31T17:56:18","isFullCredit":false},{"lineNumber":46,"author":{"gitId":"-"},"content":" get_reposense_jar(\u0027https://api.github.com/repos/reposense/RepoSense/commits/\u0027 + commit, commit\u003dcommit)","lastModifiedDate":"2021-03-31T17:56:18","isFullCredit":false},{"lineNumber":47,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2021-03-31T17:56:18","isFullCredit":false},{"lineNumber":48,"author":{"gitId":"-"},"content":"def handle_specific_release(tag):","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":49,"author":{"gitId":"-"},"content":" get_reposense_jar(\u0027https://api.github.com/repos/reposense/RepoSense/releases/tags/\u0027 + tag, tag\u003dtag)","lastModifiedDate":"2021-03-31T17:56:18","isFullCredit":false},{"lineNumber":50,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":51,"author":{"gitId":"-"},"content":"def handle_latest_release():","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":52,"author":{"gitId":"-"},"content":" get_reposense_jar(\u0027https://api.github.com/repos/reposense/RepoSense/releases/latest\u0027)","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":53,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":54,"author":{"gitId":"-"},"content":"def get_reposense_jar(url, tag\u003dNone, commit\u003dNone):","lastModifiedDate":"2021-03-31T17:56:18","isFullCredit":false},{"lineNumber":55,"author":{"gitId":"-"},"content":" response \u003d requests.get(url)","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":56,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":57,"author":{"gitId":"-"},"content":" if tag and response.status_code \u003d\u003d 404:","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":58,"author":{"gitId":"-"},"content":" print(\u0027Error, the provided tag does not exist!\u0027)","lastModifiedDate":"2021-03-31T17:56:18","isFullCredit":false},{"lineNumber":59,"author":{"gitId":"-"},"content":" exit(1)","lastModifiedDate":"2021-03-31T17:56:18","isFullCredit":false},{"lineNumber":60,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2021-03-31T17:56:18","isFullCredit":false},{"lineNumber":61,"author":{"gitId":"-"},"content":" if commit and response.status_code in [404, 422]:","lastModifiedDate":"2021-03-31T17:56:18","isFullCredit":false},{"lineNumber":62,"author":{"gitId":"-"},"content":" print(\u0027Error, the provided commit does not exist!\u0027)","lastModifiedDate":"2021-03-31T17:56:18","isFullCredit":false},{"lineNumber":63,"author":{"gitId":"-"},"content":" exit(1)","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":64,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":65,"author":{"gitId":"-"},"content":" if response.status_code in [403, 500]:","lastModifiedDate":"2021-03-31T17:56:18","isFullCredit":false},{"lineNumber":66,"author":{"gitId":"-"},"content":" print(\u0027GitHub API has exceed the rate limit. Falling back to alternative method...\u0027)","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":67,"author":{"gitId":"-"},"content":" clone_and_make_reposense(tag\u003dtag, commit\u003dcommit)","lastModifiedDate":"2021-03-31T17:56:18","isFullCredit":false},{"lineNumber":68,"author":{"gitId":"-"},"content":" return","lastModifiedDate":"2021-03-31T17:56:18","isFullCredit":false},{"lineNumber":69,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2021-03-31T17:56:18","isFullCredit":false},{"lineNumber":70,"author":{"gitId":"-"},"content":" if commit:","lastModifiedDate":"2021-03-31T17:56:18","isFullCredit":false},{"lineNumber":71,"author":{"gitId":"-"},"content":" clone_and_make_reposense(commit\u003dcommit)","lastModifiedDate":"2021-03-31T17:56:18","isFullCredit":false},{"lineNumber":72,"author":{"gitId":"-"},"content":" return","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":73,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":74,"author":{"gitId":"-"},"content":" url \u003d response.json()[\u0027assets\u0027][0][\u0027browser_download_url\u0027]","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":75,"author":{"gitId":"-"},"content":" download_file(url)","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":76,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":77,"author":{"gitId":"-"},"content":"def clone_and_make_reposense(tag\u003dNone, commit\u003dNone):","lastModifiedDate":"2021-03-31T17:56:18","isFullCredit":false},{"lineNumber":78,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":79,"author":{"gitId":"-"},"content":" # Cleanup cached RepoSense folder","lastModifiedDate":"2019-01-26T21:42:39","isFullCredit":false},{"lineNumber":80,"author":{"gitId":"-"},"content":" shutil.rmtree(\u0027RepoSense\u0027, ignore_errors\u003dTrue)","lastModifiedDate":"2019-01-26T21:42:39","isFullCredit":false},{"lineNumber":81,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-26T21:42:39","isFullCredit":false},{"lineNumber":82,"author":{"gitId":"-"},"content":" command \u003d \\","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":83,"author":{"gitId":"-"},"content":" \u0027\u0027\u0027","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":84,"author":{"gitId":"-"},"content":" git clone \u0027https://github.com/reposense/RepoSense.git\u0027 \u0026\u0026","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":85,"author":{"gitId":"-"},"content":" cd RepoSense \u0026\u0026","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":86,"author":{"gitId":"-"},"content":" \u0027\u0027\u0027","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":87,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":88,"author":{"gitId":"-"},"content":" if tag:","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":89,"author":{"gitId":"-"},"content":" command +\u003d \u0027git checkout tags/{} -b deploy \u0026\u0026\u0027.format(tag)","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":90,"author":{"gitId":"-"},"content":" elif commit:","lastModifiedDate":"2021-03-31T17:56:18","isFullCredit":false},{"lineNumber":91,"author":{"gitId":"-"},"content":" command +\u003d \u0027git checkout {} -b deploy \u0026\u0026\u0027.format(commit)","lastModifiedDate":"2021-03-31T17:56:18","isFullCredit":false},{"lineNumber":92,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":93,"author":{"gitId":"-"},"content":" command +\u003d \\","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":94,"author":{"gitId":"-"},"content":" \u0027\u0027\u0027","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":95,"author":{"gitId":"-"},"content":" ./gradlew zipreport shadowjar \u0026\u0026","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":96,"author":{"gitId":"-"},"content":" mv build/jar/RepoSense.jar ../","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":97,"author":{"gitId":"-"},"content":" \u0027\u0027\u0027","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":98,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":99,"author":{"gitId":"-"},"content":" subprocess.check_call(command, shell\u003dTrue)","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":100,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":101,"author":{"gitId":"-"},"content":"def download_file(url):","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":102,"author":{"gitId":"-"},"content":" response \u003d requests.get(url, allow_redirects\u003dTrue)","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":103,"author":{"gitId":"-"},"content":" open(JAR_FILENAME, \u0027wb\u0027).write(response.content)","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":104,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":105,"author":{"gitId":"-"},"content":"if __name__ \u003d\u003d \"__main__\":","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":106,"author":{"gitId":"-"},"content":" args \u003d parse_args()","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":107,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":108,"author":{"gitId":"-"},"content":" if os.path.exists(JAR_FILENAME) and args.overwrite is False:","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":109,"author":{"gitId":"-"},"content":" print(JAR_FILENAME + \u0027 already exists. Quitting.\u0027)","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":110,"author":{"gitId":"-"},"content":" exit()","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":111,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":112,"author":{"gitId":"-"},"content":" if args.tag:","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":113,"author":{"gitId":"-"},"content":" handle_specific_release(args.tag)","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":114,"author":{"gitId":"-"},"content":" exit()","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":115,"author":{"gitId":"-"},"content":" ","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":116,"author":{"gitId":"jedkohjk"},"content":" if args.latest:","lastModifiedDate":"2024-08-02T00:19:00","isFullCredit":false},{"lineNumber":117,"author":{"gitId":"jedkohjk"},"content":" handle_latest_tag(args.latest)","lastModifiedDate":"2024-08-02T00:19:00","isFullCredit":false},{"lineNumber":118,"author":{"gitId":"jedkohjk"},"content":" exit()","lastModifiedDate":"2024-08-02T00:19:00","isFullCredit":false},{"lineNumber":119,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2024-08-02T00:19:00","isFullCredit":false},{"lineNumber":120,"author":{"gitId":"-"},"content":" if args.commit:","lastModifiedDate":"2021-03-31T17:56:18","isFullCredit":false},{"lineNumber":121,"author":{"gitId":"-"},"content":" handle_specific_commit(args.commit)","lastModifiedDate":"2021-03-31T17:56:18","isFullCredit":false},{"lineNumber":122,"author":{"gitId":"-"},"content":" exit()","lastModifiedDate":"2021-03-31T17:56:18","isFullCredit":false},{"lineNumber":123,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2021-03-31T17:56:18","isFullCredit":false},{"lineNumber":124,"author":{"gitId":"-"},"content":" if args.master:","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":125,"author":{"gitId":"-"},"content":" clone_and_make_reposense()","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":126,"author":{"gitId":"-"},"content":" exit()","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":127,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":128,"author":{"gitId":"-"},"content":" # If no arguments are provided or --release","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":129,"author":{"gitId":"-"},"content":" handle_latest_release()","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false}],"authorContributionMap":{"jedkohjk":23,"-":106}},{"path":"run.sh","fileType":"other","lines":[{"lineNumber":1,"author":{"gitId":"-"},"content":"#!/bin/bash","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":2,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":3,"author":{"gitId":"-"},"content":"# Downloads a specific version of RepoSense.jar of your choice from our repository","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":4,"author":{"gitId":"-"},"content":"## Examples of supported options:","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":5,"author":{"gitId":"-"},"content":"### ./get-reposense.py --release # Gets the latest release (Stable)","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":6,"author":{"gitId":"-"},"content":"### ./get-reposense.py --master # Gets the latest master (Beta)","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":7,"author":{"gitId":"-"},"content":"### ./get-reposense.py --tag v1.6.1 # Gets a specific version","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":8,"author":{"gitId":"jedkohjk"},"content":"### ./get-reposense.py --latest v1.6 # Gets the latest version with the given tag prefix e.g. v1.6.1","lastModifiedDate":"2024-08-13T20:16:35","isFullCredit":false},{"lineNumber":9,"author":{"gitId":"-"},"content":"### ./get-reposense.py --commit abc123 # Gets a specific commit","lastModifiedDate":"2021-03-31T17:56:18","isFullCredit":false},{"lineNumber":10,"author":{"gitId":"-"},"content":"### ./get-reposense.py --release --overwrite # Overwrite RepoSense.jar, if exists, with the latest release","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":11,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":12,"author":{"gitId":"-"},"content":"./get-reposense.py --release","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":13,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":14,"author":{"gitId":"-"},"content":"# Executes RepoSense","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":15,"author":{"gitId":"-"},"content":"# Do not change the default output folder name (reposense-report)","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":16,"author":{"gitId":"-"},"content":"## Examples of other valid options; For more, please view the user guide","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":17,"author":{"gitId":"-"},"content":"### java -jar RepoSense.jar --repos https://github.com/reposense/RepoSense.git","lastModifiedDate":"2019-03-15T16:04:37","isFullCredit":false},{"lineNumber":18,"author":{"gitId":"-"},"content":"","lastModifiedDate":"2019-01-21T14:24:59","isFullCredit":false},{"lineNumber":19,"author":{"gitId":"-"},"content":"java -jar RepoSense.jar --config ./configs","lastModifiedDate":"2019-03-15T16:04:37","isFullCredit":false}],"authorContributionMap":{"jedkohjk":1,"-":18}}] diff --git a/src/systemtest/resources/ReportConfigSystemTest/dateRangeWithModifiedDateTimeInLines/expected/reposense_publish-RepoSense_master/commits.json b/src/systemtest/resources/ReportConfigSystemTest/dateRangeWithModifiedDateTimeInLines/expected/reposense_publish-RepoSense_master/commits.json new file mode 100644 index 0000000000..728a37ab0d --- /dev/null +++ b/src/systemtest/resources/ReportConfigSystemTest/dateRangeWithModifiedDateTimeInLines/expected/reposense_publish-RepoSense_master/commits.json @@ -0,0 +1 @@ +{"authorDailyContributionsMap":{"jedkohjk":[{"date":"2024-08-02T00:00:00","commitResults":[{"hash":"80185806433b561004c3d0245997a77afcc674f3","isMergeCommit":false,"messageTitle":"Add flag to get the latest release from a specified major version (#12)","messageBody":"The `--tag` flag fetches the exact specified RepoSense version, but provides no way to fetch the latest release of a specified major version.\r\n\r\nLet\u0027s introduce the `--latest` or `-l` flag to get the latest release from a specified major version.","fileTypesAndContributionMap":{"other":{"insertions":25,"deletions":0}}}]},{"date":"2024-08-13T00:00:00","commitResults":[{"hash":"3a748c5843b273dafa3080956eb138093b4b58c9","isMergeCommit":false,"messageTitle":"Clarify description of --latest flag in run.sh (#13)","messageBody":"Information about the function of the `--latest` flag is unclear.\r\n\r\nLet\u0027s clarify the description of `--latest` flag in `run.sh`.\r\n","fileTypesAndContributionMap":{"other":{"insertions":1,"deletions":1}}}]}]},"authorFileTypeContributionMap":{"jedkohjk":{"code":0,"tests":0,"docs":0,"other":24}},"authorContributionVariance":{"jedkohjk":2.7689133},"authorDisplayNameMap":{"jedkohjk":"jedkohjk"}} diff --git a/src/systemtest/resources/ReportConfigSystemTest/dateRangeWithModifiedDateTimeInLines/expected/summary.json b/src/systemtest/resources/ReportConfigSystemTest/dateRangeWithModifiedDateTimeInLines/expected/summary.json new file mode 100644 index 0000000000..a4a5abd6dd --- /dev/null +++ b/src/systemtest/resources/ReportConfigSystemTest/dateRangeWithModifiedDateTimeInLines/expected/summary.json @@ -0,0 +1 @@ +{"reportGeneratedTime":"Wed, 9 Apr 2025 16:02:12 SGT","reportGenerationTime":" 2.47 second(s)","zoneId":"Asia/Singapore","reportTitle":"RepoSense Report","repos":[{"location":{"location":"https://github.com/reposense/publish-RepoSense.git","repoName":"publish-RepoSense","organization":"reposense","domainName":"github"},"branch":"master","displayName":"reposense/publish-RepoSense[master]","outputFolderName":"reposense_publish-RepoSense_master","sinceDate":"2024-01-01T00:00:00","untilDate":"2024-12-31T23:59:59"}],"errorSet":[],"sinceDate":"2024-01-01T00:00:00","untilDate":"2024-12-31T23:59:59","isSinceDateProvided":true,"isUntilDateProvided":true,"supportedDomainUrlMap":{"NOT_RECOGNIZED":{"BRANCH":"","REPO_URL":"UNSUPPORTED","BASE_URL":"UNSUPPORTED","HISTORY_PATH":"","COMMIT_PATH":"","BLAME_PATH":""},"github":{"BRANCH":"tree/$BRANCH","REPO_URL":"https://github.com/$ORGANIZATION/$REPO_NAME/","BASE_URL":"https://github.com/","HISTORY_PATH":"commits/$BRANCH/$FILE_PATH","COMMIT_PATH":"commit/$COMMIT_HASH","BLAME_PATH":"blame/$BRANCH/$FILE_PATH"}},"isAuthorshipAnalyzed":false,"repoBlurbs":{"blurbMap":{"https://github.com/reposense/publish-RepoSense/tree/master":"Publish branch of Reposense"}},"authorBlurbs":{"blurbMap":{}},"isPortfolio":false} diff --git a/src/systemtest/resources/ReportConfigSystemTest/repo-blurbs.md b/src/systemtest/resources/ReportConfigSystemTest/repo-blurbs.md new file mode 100644 index 0000000000..25be4a7c78 --- /dev/null +++ b/src/systemtest/resources/ReportConfigSystemTest/repo-blurbs.md @@ -0,0 +1,2 @@ +https://github.com/reposense/publish-RepoSense/tree/master +Publish branch of Reposense diff --git a/src/systemtest/resources/ReportConfigSystemTest/report-config.yaml b/src/systemtest/resources/ReportConfigSystemTest/report-config.yaml new file mode 100644 index 0000000000..654f5e6236 --- /dev/null +++ b/src/systemtest/resources/ReportConfigSystemTest/report-config.yaml @@ -0,0 +1,26 @@ +title: RepoSense Report +repos: + - repo: https://github.com/reposense/publish-RepoSense.git + groups: + - group-name: code + globs: + - "**.java" + - group-name: tests + globs: + - "src/test**" + - group-name: docs + globs: + - "docs**" + - "**.adoc" + - "**.md" + branches: + - branch: master + blurb: "My project" + authors: + - author-git-host-id: jedkohjk + author-display-name: jedkohjk + author-git-author-name: jedkohjk + author-emails: + ignore-authors-list: + ignore-glob-list: + file-size-limit: 2000000 diff --git a/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRange/expected/reposense_publish-RepoSense_master/authorship.json b/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRange/expected/reposense_publish-RepoSense_master/authorship.json new file mode 100644 index 0000000000..0c971dca68 --- /dev/null +++ b/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRange/expected/reposense_publish-RepoSense_master/authorship.json @@ -0,0 +1 @@ +[{"path":"get-reposense.py","fileType":"other","lines":[{"lineNumber":1,"author":{"gitId":"-"},"content":"#!/usr/bin/env python","isFullCredit":false},{"lineNumber":2,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":3,"author":{"gitId":"-"},"content":"import argparse","isFullCredit":false},{"lineNumber":4,"author":{"gitId":"-"},"content":"import sys","isFullCredit":false},{"lineNumber":5,"author":{"gitId":"-"},"content":"import os","isFullCredit":false},{"lineNumber":6,"author":{"gitId":"-"},"content":"import shutil","isFullCredit":false},{"lineNumber":7,"author":{"gitId":"-"},"content":"import requests","isFullCredit":false},{"lineNumber":8,"author":{"gitId":"-"},"content":"import subprocess","isFullCredit":false},{"lineNumber":9,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":10,"author":{"gitId":"-"},"content":"JAR_FILENAME \u003d \u0027RepoSense.jar\u0027","isFullCredit":false},{"lineNumber":11,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":12,"author":{"gitId":"-"},"content":"def parse_args():","isFullCredit":false},{"lineNumber":13,"author":{"gitId":"-"},"content":" parser \u003d argparse.ArgumentParser(description\u003d\u0027Downloads a specific version of RepoSense.jar from our repository.\u0027)","isFullCredit":false},{"lineNumber":14,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":15,"author":{"gitId":"-"},"content":" group \u003d parser.add_mutually_exclusive_group()","isFullCredit":false},{"lineNumber":16,"author":{"gitId":"-"},"content":" group.add_argument(\u0027-r\u0027, \u0027--release\u0027, action\u003d\u0027store_true\u0027, help\u003d\u0027Get RepoSense.jar from the latest release (Stable)\u0027)","isFullCredit":false},{"lineNumber":17,"author":{"gitId":"-"},"content":" group.add_argument(\u0027-m\u0027, \u0027--master\u0027, action\u003d\u0027store_true\u0027, help\u003d\u0027Get RepoSense.jar from the latest master (Beta)\u0027)","isFullCredit":false},{"lineNumber":18,"author":{"gitId":"-"},"content":" group.add_argument(\u0027-t\u0027, \u0027--tag\u0027, help\u003d\u0027Get RepoSense.jar of a specific release version tag\u0027)","isFullCredit":false},{"lineNumber":19,"author":{"gitId":"jedkohjk"},"content":" group.add_argument(\u0027-l\u0027, \u0027--latest\u0027, help\u003d\u0027Get RepoSense.jar of the latest release of a specific version tag\u0027)","isFullCredit":false},{"lineNumber":20,"author":{"gitId":"-"},"content":" group.add_argument(\u0027-c\u0027, \u0027--commit\u0027, help\u003d\u0027Get RepoSense.jar of a specific commit\u0027)","isFullCredit":false},{"lineNumber":21,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":22,"author":{"gitId":"-"},"content":" parser.add_argument(\u0027-o\u0027, \u0027--overwrite\u0027, action\u003d\u0027store_true\u0027, help\u003d\u0027Overwrite RepoSense.jar file, if exists. Default: false\u0027)","isFullCredit":false},{"lineNumber":23,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":24,"author":{"gitId":"-"},"content":" return parser.parse_args()","isFullCredit":false},{"lineNumber":25,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":26,"author":{"gitId":"jedkohjk"},"content":"def handle_latest_tag(tag):","isFullCredit":false},{"lineNumber":27,"author":{"gitId":"jedkohjk"},"content":" page \u003d 1","isFullCredit":false},{"lineNumber":28,"author":{"gitId":"jedkohjk"},"content":" major \u003d tag.strip(\u0027. \u0027).split(\u0027.\u0027)","isFullCredit":false},{"lineNumber":29,"author":{"gitId":"jedkohjk"},"content":" while True:","isFullCredit":false},{"lineNumber":30,"author":{"gitId":"jedkohjk"},"content":" response \u003d requests.get(f\u0027https://api.github.com/repos/reposense/RepoSense/releases?per_page\u003d100\u0026page\u003d{page}\u0027)","isFullCredit":false},{"lineNumber":31,"author":{"gitId":"jedkohjk"},"content":" if response.status_code in [403, 500]:","isFullCredit":false},{"lineNumber":32,"author":{"gitId":"jedkohjk"},"content":" print(\u0027GitHub API has exceed the rate limit.\u0027)","isFullCredit":false},{"lineNumber":33,"author":{"gitId":"jedkohjk"},"content":" exit(1)","isFullCredit":false},{"lineNumber":34,"author":{"gitId":"jedkohjk"},"content":" releases \u003d response.json()","isFullCredit":false},{"lineNumber":35,"author":{"gitId":"jedkohjk"},"content":" if not releases:","isFullCredit":false},{"lineNumber":36,"author":{"gitId":"jedkohjk"},"content":" print(\u0027Error, the provided tag does not exist!\u0027)","isFullCredit":false},{"lineNumber":37,"author":{"gitId":"jedkohjk"},"content":" exit(1)","isFullCredit":false},{"lineNumber":38,"author":{"gitId":"jedkohjk"},"content":" for i in releases:","isFullCredit":false},{"lineNumber":39,"author":{"gitId":"jedkohjk"},"content":" release_tag \u003d i[\u0027tag_name\u0027]","isFullCredit":false},{"lineNumber":40,"author":{"gitId":"jedkohjk"},"content":" if release_tag.strip(\u0027. \u0027).split(\u0027.\u0027)[:len(major)] \u003d\u003d major:","isFullCredit":false},{"lineNumber":41,"author":{"gitId":"jedkohjk"},"content":" handle_specific_release(release_tag)","isFullCredit":false},{"lineNumber":42,"author":{"gitId":"jedkohjk"},"content":" exit()","isFullCredit":false},{"lineNumber":43,"author":{"gitId":"jedkohjk"},"content":" page +\u003d 1","isFullCredit":false},{"lineNumber":44,"author":{"gitId":"jedkohjk"},"content":"","isFullCredit":false},{"lineNumber":45,"author":{"gitId":"-"},"content":"def handle_specific_commit(commit):","isFullCredit":false},{"lineNumber":46,"author":{"gitId":"-"},"content":" get_reposense_jar(\u0027https://api.github.com/repos/reposense/RepoSense/commits/\u0027 + commit, commit\u003dcommit)","isFullCredit":false},{"lineNumber":47,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":48,"author":{"gitId":"-"},"content":"def handle_specific_release(tag):","isFullCredit":false},{"lineNumber":49,"author":{"gitId":"-"},"content":" get_reposense_jar(\u0027https://api.github.com/repos/reposense/RepoSense/releases/tags/\u0027 + tag, tag\u003dtag)","isFullCredit":false},{"lineNumber":50,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":51,"author":{"gitId":"-"},"content":"def handle_latest_release():","isFullCredit":false},{"lineNumber":52,"author":{"gitId":"-"},"content":" get_reposense_jar(\u0027https://api.github.com/repos/reposense/RepoSense/releases/latest\u0027)","isFullCredit":false},{"lineNumber":53,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":54,"author":{"gitId":"-"},"content":"def get_reposense_jar(url, tag\u003dNone, commit\u003dNone):","isFullCredit":false},{"lineNumber":55,"author":{"gitId":"-"},"content":" response \u003d requests.get(url)","isFullCredit":false},{"lineNumber":56,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":57,"author":{"gitId":"-"},"content":" if tag and response.status_code \u003d\u003d 404:","isFullCredit":false},{"lineNumber":58,"author":{"gitId":"-"},"content":" print(\u0027Error, the provided tag does not exist!\u0027)","isFullCredit":false},{"lineNumber":59,"author":{"gitId":"-"},"content":" exit(1)","isFullCredit":false},{"lineNumber":60,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":61,"author":{"gitId":"-"},"content":" if commit and response.status_code in [404, 422]:","isFullCredit":false},{"lineNumber":62,"author":{"gitId":"-"},"content":" print(\u0027Error, the provided commit does not exist!\u0027)","isFullCredit":false},{"lineNumber":63,"author":{"gitId":"-"},"content":" exit(1)","isFullCredit":false},{"lineNumber":64,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":65,"author":{"gitId":"-"},"content":" if response.status_code in [403, 500]:","isFullCredit":false},{"lineNumber":66,"author":{"gitId":"-"},"content":" print(\u0027GitHub API has exceed the rate limit. Falling back to alternative method...\u0027)","isFullCredit":false},{"lineNumber":67,"author":{"gitId":"-"},"content":" clone_and_make_reposense(tag\u003dtag, commit\u003dcommit)","isFullCredit":false},{"lineNumber":68,"author":{"gitId":"-"},"content":" return","isFullCredit":false},{"lineNumber":69,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":70,"author":{"gitId":"-"},"content":" if commit:","isFullCredit":false},{"lineNumber":71,"author":{"gitId":"-"},"content":" clone_and_make_reposense(commit\u003dcommit)","isFullCredit":false},{"lineNumber":72,"author":{"gitId":"-"},"content":" return","isFullCredit":false},{"lineNumber":73,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":74,"author":{"gitId":"-"},"content":" url \u003d response.json()[\u0027assets\u0027][0][\u0027browser_download_url\u0027]","isFullCredit":false},{"lineNumber":75,"author":{"gitId":"-"},"content":" download_file(url)","isFullCredit":false},{"lineNumber":76,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":77,"author":{"gitId":"-"},"content":"def clone_and_make_reposense(tag\u003dNone, commit\u003dNone):","isFullCredit":false},{"lineNumber":78,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":79,"author":{"gitId":"-"},"content":" # Cleanup cached RepoSense folder","isFullCredit":false},{"lineNumber":80,"author":{"gitId":"-"},"content":" shutil.rmtree(\u0027RepoSense\u0027, ignore_errors\u003dTrue)","isFullCredit":false},{"lineNumber":81,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":82,"author":{"gitId":"-"},"content":" command \u003d \\","isFullCredit":false},{"lineNumber":83,"author":{"gitId":"-"},"content":" \u0027\u0027\u0027","isFullCredit":false},{"lineNumber":84,"author":{"gitId":"-"},"content":" git clone \u0027https://github.com/reposense/RepoSense.git\u0027 \u0026\u0026","isFullCredit":false},{"lineNumber":85,"author":{"gitId":"-"},"content":" cd RepoSense \u0026\u0026","isFullCredit":false},{"lineNumber":86,"author":{"gitId":"-"},"content":" \u0027\u0027\u0027","isFullCredit":false},{"lineNumber":87,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":88,"author":{"gitId":"-"},"content":" if tag:","isFullCredit":false},{"lineNumber":89,"author":{"gitId":"-"},"content":" command +\u003d \u0027git checkout tags/{} -b deploy \u0026\u0026\u0027.format(tag)","isFullCredit":false},{"lineNumber":90,"author":{"gitId":"-"},"content":" elif commit:","isFullCredit":false},{"lineNumber":91,"author":{"gitId":"-"},"content":" command +\u003d \u0027git checkout {} -b deploy \u0026\u0026\u0027.format(commit)","isFullCredit":false},{"lineNumber":92,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":93,"author":{"gitId":"-"},"content":" command +\u003d \\","isFullCredit":false},{"lineNumber":94,"author":{"gitId":"-"},"content":" \u0027\u0027\u0027","isFullCredit":false},{"lineNumber":95,"author":{"gitId":"-"},"content":" ./gradlew zipreport shadowjar \u0026\u0026","isFullCredit":false},{"lineNumber":96,"author":{"gitId":"-"},"content":" mv build/jar/RepoSense.jar ../","isFullCredit":false},{"lineNumber":97,"author":{"gitId":"-"},"content":" \u0027\u0027\u0027","isFullCredit":false},{"lineNumber":98,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":99,"author":{"gitId":"-"},"content":" subprocess.check_call(command, shell\u003dTrue)","isFullCredit":false},{"lineNumber":100,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":101,"author":{"gitId":"-"},"content":"def download_file(url):","isFullCredit":false},{"lineNumber":102,"author":{"gitId":"-"},"content":" response \u003d requests.get(url, allow_redirects\u003dTrue)","isFullCredit":false},{"lineNumber":103,"author":{"gitId":"-"},"content":" open(JAR_FILENAME, \u0027wb\u0027).write(response.content)","isFullCredit":false},{"lineNumber":104,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":105,"author":{"gitId":"-"},"content":"if __name__ \u003d\u003d \"__main__\":","isFullCredit":false},{"lineNumber":106,"author":{"gitId":"-"},"content":" args \u003d parse_args()","isFullCredit":false},{"lineNumber":107,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":108,"author":{"gitId":"-"},"content":" if os.path.exists(JAR_FILENAME) and args.overwrite is False:","isFullCredit":false},{"lineNumber":109,"author":{"gitId":"-"},"content":" print(JAR_FILENAME + \u0027 already exists. Quitting.\u0027)","isFullCredit":false},{"lineNumber":110,"author":{"gitId":"-"},"content":" exit()","isFullCredit":false},{"lineNumber":111,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":112,"author":{"gitId":"-"},"content":" if args.tag:","isFullCredit":false},{"lineNumber":113,"author":{"gitId":"-"},"content":" handle_specific_release(args.tag)","isFullCredit":false},{"lineNumber":114,"author":{"gitId":"-"},"content":" exit()","isFullCredit":false},{"lineNumber":115,"author":{"gitId":"-"},"content":" ","isFullCredit":false},{"lineNumber":116,"author":{"gitId":"jedkohjk"},"content":" if args.latest:","isFullCredit":false},{"lineNumber":117,"author":{"gitId":"jedkohjk"},"content":" handle_latest_tag(args.latest)","isFullCredit":false},{"lineNumber":118,"author":{"gitId":"jedkohjk"},"content":" exit()","isFullCredit":false},{"lineNumber":119,"author":{"gitId":"jedkohjk"},"content":"","isFullCredit":false},{"lineNumber":120,"author":{"gitId":"-"},"content":" if args.commit:","isFullCredit":false},{"lineNumber":121,"author":{"gitId":"-"},"content":" handle_specific_commit(args.commit)","isFullCredit":false},{"lineNumber":122,"author":{"gitId":"-"},"content":" exit()","isFullCredit":false},{"lineNumber":123,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":124,"author":{"gitId":"-"},"content":" if args.master:","isFullCredit":false},{"lineNumber":125,"author":{"gitId":"-"},"content":" clone_and_make_reposense()","isFullCredit":false},{"lineNumber":126,"author":{"gitId":"-"},"content":" exit()","isFullCredit":false},{"lineNumber":127,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":128,"author":{"gitId":"-"},"content":" # If no arguments are provided or --release","isFullCredit":false},{"lineNumber":129,"author":{"gitId":"-"},"content":" handle_latest_release()","isFullCredit":false}],"authorContributionMap":{"jedkohjk":24,"-":105}},{"path":"run.sh","fileType":"other","lines":[{"lineNumber":1,"author":{"gitId":"-"},"content":"#!/bin/bash","isFullCredit":false},{"lineNumber":2,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":3,"author":{"gitId":"-"},"content":"# Downloads a specific version of RepoSense.jar of your choice from our repository","isFullCredit":false},{"lineNumber":4,"author":{"gitId":"-"},"content":"## Examples of supported options:","isFullCredit":false},{"lineNumber":5,"author":{"gitId":"-"},"content":"### ./get-reposense.py --release # Gets the latest release (Stable)","isFullCredit":false},{"lineNumber":6,"author":{"gitId":"-"},"content":"### ./get-reposense.py --master # Gets the latest master (Beta)","isFullCredit":false},{"lineNumber":7,"author":{"gitId":"-"},"content":"### ./get-reposense.py --tag v1.6.1 # Gets a specific version","isFullCredit":false},{"lineNumber":8,"author":{"gitId":"jedkohjk"},"content":"### ./get-reposense.py --latest v1.6 # Gets the latest version with the given tag prefix e.g. v1.6.1","isFullCredit":false},{"lineNumber":9,"author":{"gitId":"-"},"content":"### ./get-reposense.py --commit abc123 # Gets a specific commit","isFullCredit":false},{"lineNumber":10,"author":{"gitId":"-"},"content":"### ./get-reposense.py --release --overwrite # Overwrite RepoSense.jar, if exists, with the latest release","isFullCredit":false},{"lineNumber":11,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":12,"author":{"gitId":"-"},"content":"./get-reposense.py --release","isFullCredit":false},{"lineNumber":13,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":14,"author":{"gitId":"-"},"content":"# Executes RepoSense","isFullCredit":false},{"lineNumber":15,"author":{"gitId":"-"},"content":"# Do not change the default output folder name (reposense-report)","isFullCredit":false},{"lineNumber":16,"author":{"gitId":"-"},"content":"## Examples of other valid options; For more, please view the user guide","isFullCredit":false},{"lineNumber":17,"author":{"gitId":"-"},"content":"### java -jar RepoSense.jar --repos https://github.com/reposense/RepoSense.git","isFullCredit":false},{"lineNumber":18,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":19,"author":{"gitId":"-"},"content":"java -jar RepoSense.jar --config ./configs","isFullCredit":false}],"authorContributionMap":{"jedkohjk":1,"-":18}}] diff --git a/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRange/expected/reposense_publish-RepoSense_master/commits.json b/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRange/expected/reposense_publish-RepoSense_master/commits.json new file mode 100644 index 0000000000..5cf4f434d4 --- /dev/null +++ b/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRange/expected/reposense_publish-RepoSense_master/commits.json @@ -0,0 +1 @@ +{"authorDailyContributionsMap":{"jedkohjk":[{"date":"2024-08-02T00:00:00","commitResults":[{"hash":"80185806433b561004c3d0245997a77afcc674f3","isMergeCommit":false,"messageTitle":"Add flag to get the latest release from a specified major version (#12)","messageBody":"The `--tag` flag fetches the exact specified RepoSense version, but provides no way to fetch the latest release of a specified major version.\r\n\r\nLet\u0027s introduce the `--latest` or `-l` flag to get the latest release from a specified major version.","fileTypesAndContributionMap":{"other":{"insertions":25,"deletions":0}}}]},{"date":"2024-08-13T00:00:00","commitResults":[{"hash":"3a748c5843b273dafa3080956eb138093b4b58c9","isMergeCommit":false,"messageTitle":"Clarify description of --latest flag in run.sh (#13)","messageBody":"Information about the function of the `--latest` flag is unclear.\r\n\r\nLet\u0027s clarify the description of `--latest` flag in `run.sh`.\r\n","fileTypesAndContributionMap":{"other":{"insertions":1,"deletions":1}}}]}]},"authorFileTypeContributionMap":{"jedkohjk":{"code":0,"tests":0,"docs":0,"other":25}},"authorContributionVariance":{"jedkohjk":47.354168},"authorDisplayNameMap":{"jedkohjk":"jedkohjk"}} diff --git a/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRange/expected/summary.json b/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRange/expected/summary.json new file mode 100644 index 0000000000..329979b408 --- /dev/null +++ b/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRange/expected/summary.json @@ -0,0 +1 @@ +{"reportGeneratedTime":"Wed, 9 Apr 2025 15:45:33 SGT","reportGenerationTime":" 2.15 second(s)","zoneId":"Asia/Singapore","reportTitle":"RepoSense Report","repos":[{"location":{"location":"https://github.com/reposense/publish-RepoSense.git","repoName":"publish-RepoSense","organization":"reposense","domainName":"github"},"branch":"master","displayName":"reposense/publish-RepoSense[master]","outputFolderName":"reposense_publish-RepoSense_master","sinceDate":"1970-01-01T07:30:00","untilDate":"2024-12-31T23:59:59"}],"errorSet":[],"sinceDate":"2024-08-02T00:00:00","untilDate":"2024-12-31T23:59:59","isSinceDateProvided":true,"isUntilDateProvided":true,"supportedDomainUrlMap":{"NOT_RECOGNIZED":{"BRANCH":"","REPO_URL":"UNSUPPORTED","BASE_URL":"UNSUPPORTED","HISTORY_PATH":"","COMMIT_PATH":"","BLAME_PATH":""},"github":{"BRANCH":"tree/$BRANCH","REPO_URL":"https://github.com/$ORGANIZATION/$REPO_NAME/","BASE_URL":"https://github.com/","HISTORY_PATH":"commits/$BRANCH/$FILE_PATH","COMMIT_PATH":"commit/$COMMIT_HASH","BLAME_PATH":"blame/$BRANCH/$FILE_PATH"}},"isAuthorshipAnalyzed":false,"repoBlurbs":{"blurbMap":{"https://github.com/reposense/publish-RepoSense/tree/master":"Publish branch of Reposense"}},"authorBlurbs":{"blurbMap":{}},"isPortfolio":false} diff --git a/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRangeWithPortfolio/expected/reposense_publish-RepoSense_master/authorship.json b/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRangeWithPortfolio/expected/reposense_publish-RepoSense_master/authorship.json new file mode 100644 index 0000000000..0c971dca68 --- /dev/null +++ b/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRangeWithPortfolio/expected/reposense_publish-RepoSense_master/authorship.json @@ -0,0 +1 @@ +[{"path":"get-reposense.py","fileType":"other","lines":[{"lineNumber":1,"author":{"gitId":"-"},"content":"#!/usr/bin/env python","isFullCredit":false},{"lineNumber":2,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":3,"author":{"gitId":"-"},"content":"import argparse","isFullCredit":false},{"lineNumber":4,"author":{"gitId":"-"},"content":"import sys","isFullCredit":false},{"lineNumber":5,"author":{"gitId":"-"},"content":"import os","isFullCredit":false},{"lineNumber":6,"author":{"gitId":"-"},"content":"import shutil","isFullCredit":false},{"lineNumber":7,"author":{"gitId":"-"},"content":"import requests","isFullCredit":false},{"lineNumber":8,"author":{"gitId":"-"},"content":"import subprocess","isFullCredit":false},{"lineNumber":9,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":10,"author":{"gitId":"-"},"content":"JAR_FILENAME \u003d \u0027RepoSense.jar\u0027","isFullCredit":false},{"lineNumber":11,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":12,"author":{"gitId":"-"},"content":"def parse_args():","isFullCredit":false},{"lineNumber":13,"author":{"gitId":"-"},"content":" parser \u003d argparse.ArgumentParser(description\u003d\u0027Downloads a specific version of RepoSense.jar from our repository.\u0027)","isFullCredit":false},{"lineNumber":14,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":15,"author":{"gitId":"-"},"content":" group \u003d parser.add_mutually_exclusive_group()","isFullCredit":false},{"lineNumber":16,"author":{"gitId":"-"},"content":" group.add_argument(\u0027-r\u0027, \u0027--release\u0027, action\u003d\u0027store_true\u0027, help\u003d\u0027Get RepoSense.jar from the latest release (Stable)\u0027)","isFullCredit":false},{"lineNumber":17,"author":{"gitId":"-"},"content":" group.add_argument(\u0027-m\u0027, \u0027--master\u0027, action\u003d\u0027store_true\u0027, help\u003d\u0027Get RepoSense.jar from the latest master (Beta)\u0027)","isFullCredit":false},{"lineNumber":18,"author":{"gitId":"-"},"content":" group.add_argument(\u0027-t\u0027, \u0027--tag\u0027, help\u003d\u0027Get RepoSense.jar of a specific release version tag\u0027)","isFullCredit":false},{"lineNumber":19,"author":{"gitId":"jedkohjk"},"content":" group.add_argument(\u0027-l\u0027, \u0027--latest\u0027, help\u003d\u0027Get RepoSense.jar of the latest release of a specific version tag\u0027)","isFullCredit":false},{"lineNumber":20,"author":{"gitId":"-"},"content":" group.add_argument(\u0027-c\u0027, \u0027--commit\u0027, help\u003d\u0027Get RepoSense.jar of a specific commit\u0027)","isFullCredit":false},{"lineNumber":21,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":22,"author":{"gitId":"-"},"content":" parser.add_argument(\u0027-o\u0027, \u0027--overwrite\u0027, action\u003d\u0027store_true\u0027, help\u003d\u0027Overwrite RepoSense.jar file, if exists. Default: false\u0027)","isFullCredit":false},{"lineNumber":23,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":24,"author":{"gitId":"-"},"content":" return parser.parse_args()","isFullCredit":false},{"lineNumber":25,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":26,"author":{"gitId":"jedkohjk"},"content":"def handle_latest_tag(tag):","isFullCredit":false},{"lineNumber":27,"author":{"gitId":"jedkohjk"},"content":" page \u003d 1","isFullCredit":false},{"lineNumber":28,"author":{"gitId":"jedkohjk"},"content":" major \u003d tag.strip(\u0027. \u0027).split(\u0027.\u0027)","isFullCredit":false},{"lineNumber":29,"author":{"gitId":"jedkohjk"},"content":" while True:","isFullCredit":false},{"lineNumber":30,"author":{"gitId":"jedkohjk"},"content":" response \u003d requests.get(f\u0027https://api.github.com/repos/reposense/RepoSense/releases?per_page\u003d100\u0026page\u003d{page}\u0027)","isFullCredit":false},{"lineNumber":31,"author":{"gitId":"jedkohjk"},"content":" if response.status_code in [403, 500]:","isFullCredit":false},{"lineNumber":32,"author":{"gitId":"jedkohjk"},"content":" print(\u0027GitHub API has exceed the rate limit.\u0027)","isFullCredit":false},{"lineNumber":33,"author":{"gitId":"jedkohjk"},"content":" exit(1)","isFullCredit":false},{"lineNumber":34,"author":{"gitId":"jedkohjk"},"content":" releases \u003d response.json()","isFullCredit":false},{"lineNumber":35,"author":{"gitId":"jedkohjk"},"content":" if not releases:","isFullCredit":false},{"lineNumber":36,"author":{"gitId":"jedkohjk"},"content":" print(\u0027Error, the provided tag does not exist!\u0027)","isFullCredit":false},{"lineNumber":37,"author":{"gitId":"jedkohjk"},"content":" exit(1)","isFullCredit":false},{"lineNumber":38,"author":{"gitId":"jedkohjk"},"content":" for i in releases:","isFullCredit":false},{"lineNumber":39,"author":{"gitId":"jedkohjk"},"content":" release_tag \u003d i[\u0027tag_name\u0027]","isFullCredit":false},{"lineNumber":40,"author":{"gitId":"jedkohjk"},"content":" if release_tag.strip(\u0027. \u0027).split(\u0027.\u0027)[:len(major)] \u003d\u003d major:","isFullCredit":false},{"lineNumber":41,"author":{"gitId":"jedkohjk"},"content":" handle_specific_release(release_tag)","isFullCredit":false},{"lineNumber":42,"author":{"gitId":"jedkohjk"},"content":" exit()","isFullCredit":false},{"lineNumber":43,"author":{"gitId":"jedkohjk"},"content":" page +\u003d 1","isFullCredit":false},{"lineNumber":44,"author":{"gitId":"jedkohjk"},"content":"","isFullCredit":false},{"lineNumber":45,"author":{"gitId":"-"},"content":"def handle_specific_commit(commit):","isFullCredit":false},{"lineNumber":46,"author":{"gitId":"-"},"content":" get_reposense_jar(\u0027https://api.github.com/repos/reposense/RepoSense/commits/\u0027 + commit, commit\u003dcommit)","isFullCredit":false},{"lineNumber":47,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":48,"author":{"gitId":"-"},"content":"def handle_specific_release(tag):","isFullCredit":false},{"lineNumber":49,"author":{"gitId":"-"},"content":" get_reposense_jar(\u0027https://api.github.com/repos/reposense/RepoSense/releases/tags/\u0027 + tag, tag\u003dtag)","isFullCredit":false},{"lineNumber":50,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":51,"author":{"gitId":"-"},"content":"def handle_latest_release():","isFullCredit":false},{"lineNumber":52,"author":{"gitId":"-"},"content":" get_reposense_jar(\u0027https://api.github.com/repos/reposense/RepoSense/releases/latest\u0027)","isFullCredit":false},{"lineNumber":53,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":54,"author":{"gitId":"-"},"content":"def get_reposense_jar(url, tag\u003dNone, commit\u003dNone):","isFullCredit":false},{"lineNumber":55,"author":{"gitId":"-"},"content":" response \u003d requests.get(url)","isFullCredit":false},{"lineNumber":56,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":57,"author":{"gitId":"-"},"content":" if tag and response.status_code \u003d\u003d 404:","isFullCredit":false},{"lineNumber":58,"author":{"gitId":"-"},"content":" print(\u0027Error, the provided tag does not exist!\u0027)","isFullCredit":false},{"lineNumber":59,"author":{"gitId":"-"},"content":" exit(1)","isFullCredit":false},{"lineNumber":60,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":61,"author":{"gitId":"-"},"content":" if commit and response.status_code in [404, 422]:","isFullCredit":false},{"lineNumber":62,"author":{"gitId":"-"},"content":" print(\u0027Error, the provided commit does not exist!\u0027)","isFullCredit":false},{"lineNumber":63,"author":{"gitId":"-"},"content":" exit(1)","isFullCredit":false},{"lineNumber":64,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":65,"author":{"gitId":"-"},"content":" if response.status_code in [403, 500]:","isFullCredit":false},{"lineNumber":66,"author":{"gitId":"-"},"content":" print(\u0027GitHub API has exceed the rate limit. Falling back to alternative method...\u0027)","isFullCredit":false},{"lineNumber":67,"author":{"gitId":"-"},"content":" clone_and_make_reposense(tag\u003dtag, commit\u003dcommit)","isFullCredit":false},{"lineNumber":68,"author":{"gitId":"-"},"content":" return","isFullCredit":false},{"lineNumber":69,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":70,"author":{"gitId":"-"},"content":" if commit:","isFullCredit":false},{"lineNumber":71,"author":{"gitId":"-"},"content":" clone_and_make_reposense(commit\u003dcommit)","isFullCredit":false},{"lineNumber":72,"author":{"gitId":"-"},"content":" return","isFullCredit":false},{"lineNumber":73,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":74,"author":{"gitId":"-"},"content":" url \u003d response.json()[\u0027assets\u0027][0][\u0027browser_download_url\u0027]","isFullCredit":false},{"lineNumber":75,"author":{"gitId":"-"},"content":" download_file(url)","isFullCredit":false},{"lineNumber":76,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":77,"author":{"gitId":"-"},"content":"def clone_and_make_reposense(tag\u003dNone, commit\u003dNone):","isFullCredit":false},{"lineNumber":78,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":79,"author":{"gitId":"-"},"content":" # Cleanup cached RepoSense folder","isFullCredit":false},{"lineNumber":80,"author":{"gitId":"-"},"content":" shutil.rmtree(\u0027RepoSense\u0027, ignore_errors\u003dTrue)","isFullCredit":false},{"lineNumber":81,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":82,"author":{"gitId":"-"},"content":" command \u003d \\","isFullCredit":false},{"lineNumber":83,"author":{"gitId":"-"},"content":" \u0027\u0027\u0027","isFullCredit":false},{"lineNumber":84,"author":{"gitId":"-"},"content":" git clone \u0027https://github.com/reposense/RepoSense.git\u0027 \u0026\u0026","isFullCredit":false},{"lineNumber":85,"author":{"gitId":"-"},"content":" cd RepoSense \u0026\u0026","isFullCredit":false},{"lineNumber":86,"author":{"gitId":"-"},"content":" \u0027\u0027\u0027","isFullCredit":false},{"lineNumber":87,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":88,"author":{"gitId":"-"},"content":" if tag:","isFullCredit":false},{"lineNumber":89,"author":{"gitId":"-"},"content":" command +\u003d \u0027git checkout tags/{} -b deploy \u0026\u0026\u0027.format(tag)","isFullCredit":false},{"lineNumber":90,"author":{"gitId":"-"},"content":" elif commit:","isFullCredit":false},{"lineNumber":91,"author":{"gitId":"-"},"content":" command +\u003d \u0027git checkout {} -b deploy \u0026\u0026\u0027.format(commit)","isFullCredit":false},{"lineNumber":92,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":93,"author":{"gitId":"-"},"content":" command +\u003d \\","isFullCredit":false},{"lineNumber":94,"author":{"gitId":"-"},"content":" \u0027\u0027\u0027","isFullCredit":false},{"lineNumber":95,"author":{"gitId":"-"},"content":" ./gradlew zipreport shadowjar \u0026\u0026","isFullCredit":false},{"lineNumber":96,"author":{"gitId":"-"},"content":" mv build/jar/RepoSense.jar ../","isFullCredit":false},{"lineNumber":97,"author":{"gitId":"-"},"content":" \u0027\u0027\u0027","isFullCredit":false},{"lineNumber":98,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":99,"author":{"gitId":"-"},"content":" subprocess.check_call(command, shell\u003dTrue)","isFullCredit":false},{"lineNumber":100,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":101,"author":{"gitId":"-"},"content":"def download_file(url):","isFullCredit":false},{"lineNumber":102,"author":{"gitId":"-"},"content":" response \u003d requests.get(url, allow_redirects\u003dTrue)","isFullCredit":false},{"lineNumber":103,"author":{"gitId":"-"},"content":" open(JAR_FILENAME, \u0027wb\u0027).write(response.content)","isFullCredit":false},{"lineNumber":104,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":105,"author":{"gitId":"-"},"content":"if __name__ \u003d\u003d \"__main__\":","isFullCredit":false},{"lineNumber":106,"author":{"gitId":"-"},"content":" args \u003d parse_args()","isFullCredit":false},{"lineNumber":107,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":108,"author":{"gitId":"-"},"content":" if os.path.exists(JAR_FILENAME) and args.overwrite is False:","isFullCredit":false},{"lineNumber":109,"author":{"gitId":"-"},"content":" print(JAR_FILENAME + \u0027 already exists. Quitting.\u0027)","isFullCredit":false},{"lineNumber":110,"author":{"gitId":"-"},"content":" exit()","isFullCredit":false},{"lineNumber":111,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":112,"author":{"gitId":"-"},"content":" if args.tag:","isFullCredit":false},{"lineNumber":113,"author":{"gitId":"-"},"content":" handle_specific_release(args.tag)","isFullCredit":false},{"lineNumber":114,"author":{"gitId":"-"},"content":" exit()","isFullCredit":false},{"lineNumber":115,"author":{"gitId":"-"},"content":" ","isFullCredit":false},{"lineNumber":116,"author":{"gitId":"jedkohjk"},"content":" if args.latest:","isFullCredit":false},{"lineNumber":117,"author":{"gitId":"jedkohjk"},"content":" handle_latest_tag(args.latest)","isFullCredit":false},{"lineNumber":118,"author":{"gitId":"jedkohjk"},"content":" exit()","isFullCredit":false},{"lineNumber":119,"author":{"gitId":"jedkohjk"},"content":"","isFullCredit":false},{"lineNumber":120,"author":{"gitId":"-"},"content":" if args.commit:","isFullCredit":false},{"lineNumber":121,"author":{"gitId":"-"},"content":" handle_specific_commit(args.commit)","isFullCredit":false},{"lineNumber":122,"author":{"gitId":"-"},"content":" exit()","isFullCredit":false},{"lineNumber":123,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":124,"author":{"gitId":"-"},"content":" if args.master:","isFullCredit":false},{"lineNumber":125,"author":{"gitId":"-"},"content":" clone_and_make_reposense()","isFullCredit":false},{"lineNumber":126,"author":{"gitId":"-"},"content":" exit()","isFullCredit":false},{"lineNumber":127,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":128,"author":{"gitId":"-"},"content":" # If no arguments are provided or --release","isFullCredit":false},{"lineNumber":129,"author":{"gitId":"-"},"content":" handle_latest_release()","isFullCredit":false}],"authorContributionMap":{"jedkohjk":24,"-":105}},{"path":"run.sh","fileType":"other","lines":[{"lineNumber":1,"author":{"gitId":"-"},"content":"#!/bin/bash","isFullCredit":false},{"lineNumber":2,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":3,"author":{"gitId":"-"},"content":"# Downloads a specific version of RepoSense.jar of your choice from our repository","isFullCredit":false},{"lineNumber":4,"author":{"gitId":"-"},"content":"## Examples of supported options:","isFullCredit":false},{"lineNumber":5,"author":{"gitId":"-"},"content":"### ./get-reposense.py --release # Gets the latest release (Stable)","isFullCredit":false},{"lineNumber":6,"author":{"gitId":"-"},"content":"### ./get-reposense.py --master # Gets the latest master (Beta)","isFullCredit":false},{"lineNumber":7,"author":{"gitId":"-"},"content":"### ./get-reposense.py --tag v1.6.1 # Gets a specific version","isFullCredit":false},{"lineNumber":8,"author":{"gitId":"jedkohjk"},"content":"### ./get-reposense.py --latest v1.6 # Gets the latest version with the given tag prefix e.g. v1.6.1","isFullCredit":false},{"lineNumber":9,"author":{"gitId":"-"},"content":"### ./get-reposense.py --commit abc123 # Gets a specific commit","isFullCredit":false},{"lineNumber":10,"author":{"gitId":"-"},"content":"### ./get-reposense.py --release --overwrite # Overwrite RepoSense.jar, if exists, with the latest release","isFullCredit":false},{"lineNumber":11,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":12,"author":{"gitId":"-"},"content":"./get-reposense.py --release","isFullCredit":false},{"lineNumber":13,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":14,"author":{"gitId":"-"},"content":"# Executes RepoSense","isFullCredit":false},{"lineNumber":15,"author":{"gitId":"-"},"content":"# Do not change the default output folder name (reposense-report)","isFullCredit":false},{"lineNumber":16,"author":{"gitId":"-"},"content":"## Examples of other valid options; For more, please view the user guide","isFullCredit":false},{"lineNumber":17,"author":{"gitId":"-"},"content":"### java -jar RepoSense.jar --repos https://github.com/reposense/RepoSense.git","isFullCredit":false},{"lineNumber":18,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":19,"author":{"gitId":"-"},"content":"java -jar RepoSense.jar --config ./configs","isFullCredit":false}],"authorContributionMap":{"jedkohjk":1,"-":18}}] diff --git a/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRangeWithPortfolio/expected/reposense_publish-RepoSense_master/commits.json b/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRangeWithPortfolio/expected/reposense_publish-RepoSense_master/commits.json new file mode 100644 index 0000000000..5cf4f434d4 --- /dev/null +++ b/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRangeWithPortfolio/expected/reposense_publish-RepoSense_master/commits.json @@ -0,0 +1 @@ +{"authorDailyContributionsMap":{"jedkohjk":[{"date":"2024-08-02T00:00:00","commitResults":[{"hash":"80185806433b561004c3d0245997a77afcc674f3","isMergeCommit":false,"messageTitle":"Add flag to get the latest release from a specified major version (#12)","messageBody":"The `--tag` flag fetches the exact specified RepoSense version, but provides no way to fetch the latest release of a specified major version.\r\n\r\nLet\u0027s introduce the `--latest` or `-l` flag to get the latest release from a specified major version.","fileTypesAndContributionMap":{"other":{"insertions":25,"deletions":0}}}]},{"date":"2024-08-13T00:00:00","commitResults":[{"hash":"3a748c5843b273dafa3080956eb138093b4b58c9","isMergeCommit":false,"messageTitle":"Clarify description of --latest flag in run.sh (#13)","messageBody":"Information about the function of the `--latest` flag is unclear.\r\n\r\nLet\u0027s clarify the description of `--latest` flag in `run.sh`.\r\n","fileTypesAndContributionMap":{"other":{"insertions":1,"deletions":1}}}]}]},"authorFileTypeContributionMap":{"jedkohjk":{"code":0,"tests":0,"docs":0,"other":25}},"authorContributionVariance":{"jedkohjk":47.354168},"authorDisplayNameMap":{"jedkohjk":"jedkohjk"}} diff --git a/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRangeWithPortfolio/expected/summary.json b/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRangeWithPortfolio/expected/summary.json new file mode 100644 index 0000000000..a1df721fc6 --- /dev/null +++ b/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRangeWithPortfolio/expected/summary.json @@ -0,0 +1 @@ +{"reportGeneratedTime":"Wed, 9 Apr 2025 15:59:47 SGT","reportGenerationTime":" 2.43 second(s)","zoneId":"Asia/Singapore","reportTitle":"RepoSense Report","repos":[{"location":{"location":"https://github.com/reposense/publish-RepoSense.git","repoName":"publish-RepoSense","organization":"reposense","domainName":"github"},"branch":"master","displayName":"reposense/publish-RepoSense[master]","outputFolderName":"reposense_publish-RepoSense_master","sinceDate":"1970-01-01T07:30:00","untilDate":"2024-08-31T23:59:59"}],"errorSet":[],"sinceDate":"2024-08-02T00:00:00","untilDate":"2024-08-31T23:59:59","isSinceDateProvided":true,"isUntilDateProvided":true,"supportedDomainUrlMap":{"NOT_RECOGNIZED":{"BRANCH":"","REPO_URL":"UNSUPPORTED","BASE_URL":"UNSUPPORTED","HISTORY_PATH":"","COMMIT_PATH":"","BLAME_PATH":""},"github":{"BRANCH":"tree/$BRANCH","REPO_URL":"https://github.com/$ORGANIZATION/$REPO_NAME/","BASE_URL":"https://github.com/","HISTORY_PATH":"commits/$BRANCH/$FILE_PATH","COMMIT_PATH":"commit/$COMMIT_HASH","BLAME_PATH":"blame/$BRANCH/$FILE_PATH"}},"isAuthorshipAnalyzed":false,"repoBlurbs":{"blurbMap":{"https://github.com/reposense/publish-RepoSense/tree/master":"Publish branch of Reposense"}},"authorBlurbs":{"blurbMap":{}},"isPortfolio":true} diff --git a/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRangeWithShallowCloning/expected/reposense_publish-RepoSense_master/authorship.json b/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRangeWithShallowCloning/expected/reposense_publish-RepoSense_master/authorship.json new file mode 100644 index 0000000000..0c971dca68 --- /dev/null +++ b/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRangeWithShallowCloning/expected/reposense_publish-RepoSense_master/authorship.json @@ -0,0 +1 @@ +[{"path":"get-reposense.py","fileType":"other","lines":[{"lineNumber":1,"author":{"gitId":"-"},"content":"#!/usr/bin/env python","isFullCredit":false},{"lineNumber":2,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":3,"author":{"gitId":"-"},"content":"import argparse","isFullCredit":false},{"lineNumber":4,"author":{"gitId":"-"},"content":"import sys","isFullCredit":false},{"lineNumber":5,"author":{"gitId":"-"},"content":"import os","isFullCredit":false},{"lineNumber":6,"author":{"gitId":"-"},"content":"import shutil","isFullCredit":false},{"lineNumber":7,"author":{"gitId":"-"},"content":"import requests","isFullCredit":false},{"lineNumber":8,"author":{"gitId":"-"},"content":"import subprocess","isFullCredit":false},{"lineNumber":9,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":10,"author":{"gitId":"-"},"content":"JAR_FILENAME \u003d \u0027RepoSense.jar\u0027","isFullCredit":false},{"lineNumber":11,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":12,"author":{"gitId":"-"},"content":"def parse_args():","isFullCredit":false},{"lineNumber":13,"author":{"gitId":"-"},"content":" parser \u003d argparse.ArgumentParser(description\u003d\u0027Downloads a specific version of RepoSense.jar from our repository.\u0027)","isFullCredit":false},{"lineNumber":14,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":15,"author":{"gitId":"-"},"content":" group \u003d parser.add_mutually_exclusive_group()","isFullCredit":false},{"lineNumber":16,"author":{"gitId":"-"},"content":" group.add_argument(\u0027-r\u0027, \u0027--release\u0027, action\u003d\u0027store_true\u0027, help\u003d\u0027Get RepoSense.jar from the latest release (Stable)\u0027)","isFullCredit":false},{"lineNumber":17,"author":{"gitId":"-"},"content":" group.add_argument(\u0027-m\u0027, \u0027--master\u0027, action\u003d\u0027store_true\u0027, help\u003d\u0027Get RepoSense.jar from the latest master (Beta)\u0027)","isFullCredit":false},{"lineNumber":18,"author":{"gitId":"-"},"content":" group.add_argument(\u0027-t\u0027, \u0027--tag\u0027, help\u003d\u0027Get RepoSense.jar of a specific release version tag\u0027)","isFullCredit":false},{"lineNumber":19,"author":{"gitId":"jedkohjk"},"content":" group.add_argument(\u0027-l\u0027, \u0027--latest\u0027, help\u003d\u0027Get RepoSense.jar of the latest release of a specific version tag\u0027)","isFullCredit":false},{"lineNumber":20,"author":{"gitId":"-"},"content":" group.add_argument(\u0027-c\u0027, \u0027--commit\u0027, help\u003d\u0027Get RepoSense.jar of a specific commit\u0027)","isFullCredit":false},{"lineNumber":21,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":22,"author":{"gitId":"-"},"content":" parser.add_argument(\u0027-o\u0027, \u0027--overwrite\u0027, action\u003d\u0027store_true\u0027, help\u003d\u0027Overwrite RepoSense.jar file, if exists. Default: false\u0027)","isFullCredit":false},{"lineNumber":23,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":24,"author":{"gitId":"-"},"content":" return parser.parse_args()","isFullCredit":false},{"lineNumber":25,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":26,"author":{"gitId":"jedkohjk"},"content":"def handle_latest_tag(tag):","isFullCredit":false},{"lineNumber":27,"author":{"gitId":"jedkohjk"},"content":" page \u003d 1","isFullCredit":false},{"lineNumber":28,"author":{"gitId":"jedkohjk"},"content":" major \u003d tag.strip(\u0027. \u0027).split(\u0027.\u0027)","isFullCredit":false},{"lineNumber":29,"author":{"gitId":"jedkohjk"},"content":" while True:","isFullCredit":false},{"lineNumber":30,"author":{"gitId":"jedkohjk"},"content":" response \u003d requests.get(f\u0027https://api.github.com/repos/reposense/RepoSense/releases?per_page\u003d100\u0026page\u003d{page}\u0027)","isFullCredit":false},{"lineNumber":31,"author":{"gitId":"jedkohjk"},"content":" if response.status_code in [403, 500]:","isFullCredit":false},{"lineNumber":32,"author":{"gitId":"jedkohjk"},"content":" print(\u0027GitHub API has exceed the rate limit.\u0027)","isFullCredit":false},{"lineNumber":33,"author":{"gitId":"jedkohjk"},"content":" exit(1)","isFullCredit":false},{"lineNumber":34,"author":{"gitId":"jedkohjk"},"content":" releases \u003d response.json()","isFullCredit":false},{"lineNumber":35,"author":{"gitId":"jedkohjk"},"content":" if not releases:","isFullCredit":false},{"lineNumber":36,"author":{"gitId":"jedkohjk"},"content":" print(\u0027Error, the provided tag does not exist!\u0027)","isFullCredit":false},{"lineNumber":37,"author":{"gitId":"jedkohjk"},"content":" exit(1)","isFullCredit":false},{"lineNumber":38,"author":{"gitId":"jedkohjk"},"content":" for i in releases:","isFullCredit":false},{"lineNumber":39,"author":{"gitId":"jedkohjk"},"content":" release_tag \u003d i[\u0027tag_name\u0027]","isFullCredit":false},{"lineNumber":40,"author":{"gitId":"jedkohjk"},"content":" if release_tag.strip(\u0027. \u0027).split(\u0027.\u0027)[:len(major)] \u003d\u003d major:","isFullCredit":false},{"lineNumber":41,"author":{"gitId":"jedkohjk"},"content":" handle_specific_release(release_tag)","isFullCredit":false},{"lineNumber":42,"author":{"gitId":"jedkohjk"},"content":" exit()","isFullCredit":false},{"lineNumber":43,"author":{"gitId":"jedkohjk"},"content":" page +\u003d 1","isFullCredit":false},{"lineNumber":44,"author":{"gitId":"jedkohjk"},"content":"","isFullCredit":false},{"lineNumber":45,"author":{"gitId":"-"},"content":"def handle_specific_commit(commit):","isFullCredit":false},{"lineNumber":46,"author":{"gitId":"-"},"content":" get_reposense_jar(\u0027https://api.github.com/repos/reposense/RepoSense/commits/\u0027 + commit, commit\u003dcommit)","isFullCredit":false},{"lineNumber":47,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":48,"author":{"gitId":"-"},"content":"def handle_specific_release(tag):","isFullCredit":false},{"lineNumber":49,"author":{"gitId":"-"},"content":" get_reposense_jar(\u0027https://api.github.com/repos/reposense/RepoSense/releases/tags/\u0027 + tag, tag\u003dtag)","isFullCredit":false},{"lineNumber":50,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":51,"author":{"gitId":"-"},"content":"def handle_latest_release():","isFullCredit":false},{"lineNumber":52,"author":{"gitId":"-"},"content":" get_reposense_jar(\u0027https://api.github.com/repos/reposense/RepoSense/releases/latest\u0027)","isFullCredit":false},{"lineNumber":53,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":54,"author":{"gitId":"-"},"content":"def get_reposense_jar(url, tag\u003dNone, commit\u003dNone):","isFullCredit":false},{"lineNumber":55,"author":{"gitId":"-"},"content":" response \u003d requests.get(url)","isFullCredit":false},{"lineNumber":56,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":57,"author":{"gitId":"-"},"content":" if tag and response.status_code \u003d\u003d 404:","isFullCredit":false},{"lineNumber":58,"author":{"gitId":"-"},"content":" print(\u0027Error, the provided tag does not exist!\u0027)","isFullCredit":false},{"lineNumber":59,"author":{"gitId":"-"},"content":" exit(1)","isFullCredit":false},{"lineNumber":60,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":61,"author":{"gitId":"-"},"content":" if commit and response.status_code in [404, 422]:","isFullCredit":false},{"lineNumber":62,"author":{"gitId":"-"},"content":" print(\u0027Error, the provided commit does not exist!\u0027)","isFullCredit":false},{"lineNumber":63,"author":{"gitId":"-"},"content":" exit(1)","isFullCredit":false},{"lineNumber":64,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":65,"author":{"gitId":"-"},"content":" if response.status_code in [403, 500]:","isFullCredit":false},{"lineNumber":66,"author":{"gitId":"-"},"content":" print(\u0027GitHub API has exceed the rate limit. Falling back to alternative method...\u0027)","isFullCredit":false},{"lineNumber":67,"author":{"gitId":"-"},"content":" clone_and_make_reposense(tag\u003dtag, commit\u003dcommit)","isFullCredit":false},{"lineNumber":68,"author":{"gitId":"-"},"content":" return","isFullCredit":false},{"lineNumber":69,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":70,"author":{"gitId":"-"},"content":" if commit:","isFullCredit":false},{"lineNumber":71,"author":{"gitId":"-"},"content":" clone_and_make_reposense(commit\u003dcommit)","isFullCredit":false},{"lineNumber":72,"author":{"gitId":"-"},"content":" return","isFullCredit":false},{"lineNumber":73,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":74,"author":{"gitId":"-"},"content":" url \u003d response.json()[\u0027assets\u0027][0][\u0027browser_download_url\u0027]","isFullCredit":false},{"lineNumber":75,"author":{"gitId":"-"},"content":" download_file(url)","isFullCredit":false},{"lineNumber":76,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":77,"author":{"gitId":"-"},"content":"def clone_and_make_reposense(tag\u003dNone, commit\u003dNone):","isFullCredit":false},{"lineNumber":78,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":79,"author":{"gitId":"-"},"content":" # Cleanup cached RepoSense folder","isFullCredit":false},{"lineNumber":80,"author":{"gitId":"-"},"content":" shutil.rmtree(\u0027RepoSense\u0027, ignore_errors\u003dTrue)","isFullCredit":false},{"lineNumber":81,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":82,"author":{"gitId":"-"},"content":" command \u003d \\","isFullCredit":false},{"lineNumber":83,"author":{"gitId":"-"},"content":" \u0027\u0027\u0027","isFullCredit":false},{"lineNumber":84,"author":{"gitId":"-"},"content":" git clone \u0027https://github.com/reposense/RepoSense.git\u0027 \u0026\u0026","isFullCredit":false},{"lineNumber":85,"author":{"gitId":"-"},"content":" cd RepoSense \u0026\u0026","isFullCredit":false},{"lineNumber":86,"author":{"gitId":"-"},"content":" \u0027\u0027\u0027","isFullCredit":false},{"lineNumber":87,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":88,"author":{"gitId":"-"},"content":" if tag:","isFullCredit":false},{"lineNumber":89,"author":{"gitId":"-"},"content":" command +\u003d \u0027git checkout tags/{} -b deploy \u0026\u0026\u0027.format(tag)","isFullCredit":false},{"lineNumber":90,"author":{"gitId":"-"},"content":" elif commit:","isFullCredit":false},{"lineNumber":91,"author":{"gitId":"-"},"content":" command +\u003d \u0027git checkout {} -b deploy \u0026\u0026\u0027.format(commit)","isFullCredit":false},{"lineNumber":92,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":93,"author":{"gitId":"-"},"content":" command +\u003d \\","isFullCredit":false},{"lineNumber":94,"author":{"gitId":"-"},"content":" \u0027\u0027\u0027","isFullCredit":false},{"lineNumber":95,"author":{"gitId":"-"},"content":" ./gradlew zipreport shadowjar \u0026\u0026","isFullCredit":false},{"lineNumber":96,"author":{"gitId":"-"},"content":" mv build/jar/RepoSense.jar ../","isFullCredit":false},{"lineNumber":97,"author":{"gitId":"-"},"content":" \u0027\u0027\u0027","isFullCredit":false},{"lineNumber":98,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":99,"author":{"gitId":"-"},"content":" subprocess.check_call(command, shell\u003dTrue)","isFullCredit":false},{"lineNumber":100,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":101,"author":{"gitId":"-"},"content":"def download_file(url):","isFullCredit":false},{"lineNumber":102,"author":{"gitId":"-"},"content":" response \u003d requests.get(url, allow_redirects\u003dTrue)","isFullCredit":false},{"lineNumber":103,"author":{"gitId":"-"},"content":" open(JAR_FILENAME, \u0027wb\u0027).write(response.content)","isFullCredit":false},{"lineNumber":104,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":105,"author":{"gitId":"-"},"content":"if __name__ \u003d\u003d \"__main__\":","isFullCredit":false},{"lineNumber":106,"author":{"gitId":"-"},"content":" args \u003d parse_args()","isFullCredit":false},{"lineNumber":107,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":108,"author":{"gitId":"-"},"content":" if os.path.exists(JAR_FILENAME) and args.overwrite is False:","isFullCredit":false},{"lineNumber":109,"author":{"gitId":"-"},"content":" print(JAR_FILENAME + \u0027 already exists. Quitting.\u0027)","isFullCredit":false},{"lineNumber":110,"author":{"gitId":"-"},"content":" exit()","isFullCredit":false},{"lineNumber":111,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":112,"author":{"gitId":"-"},"content":" if args.tag:","isFullCredit":false},{"lineNumber":113,"author":{"gitId":"-"},"content":" handle_specific_release(args.tag)","isFullCredit":false},{"lineNumber":114,"author":{"gitId":"-"},"content":" exit()","isFullCredit":false},{"lineNumber":115,"author":{"gitId":"-"},"content":" ","isFullCredit":false},{"lineNumber":116,"author":{"gitId":"jedkohjk"},"content":" if args.latest:","isFullCredit":false},{"lineNumber":117,"author":{"gitId":"jedkohjk"},"content":" handle_latest_tag(args.latest)","isFullCredit":false},{"lineNumber":118,"author":{"gitId":"jedkohjk"},"content":" exit()","isFullCredit":false},{"lineNumber":119,"author":{"gitId":"jedkohjk"},"content":"","isFullCredit":false},{"lineNumber":120,"author":{"gitId":"-"},"content":" if args.commit:","isFullCredit":false},{"lineNumber":121,"author":{"gitId":"-"},"content":" handle_specific_commit(args.commit)","isFullCredit":false},{"lineNumber":122,"author":{"gitId":"-"},"content":" exit()","isFullCredit":false},{"lineNumber":123,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":124,"author":{"gitId":"-"},"content":" if args.master:","isFullCredit":false},{"lineNumber":125,"author":{"gitId":"-"},"content":" clone_and_make_reposense()","isFullCredit":false},{"lineNumber":126,"author":{"gitId":"-"},"content":" exit()","isFullCredit":false},{"lineNumber":127,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":128,"author":{"gitId":"-"},"content":" # If no arguments are provided or --release","isFullCredit":false},{"lineNumber":129,"author":{"gitId":"-"},"content":" handle_latest_release()","isFullCredit":false}],"authorContributionMap":{"jedkohjk":24,"-":105}},{"path":"run.sh","fileType":"other","lines":[{"lineNumber":1,"author":{"gitId":"-"},"content":"#!/bin/bash","isFullCredit":false},{"lineNumber":2,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":3,"author":{"gitId":"-"},"content":"# Downloads a specific version of RepoSense.jar of your choice from our repository","isFullCredit":false},{"lineNumber":4,"author":{"gitId":"-"},"content":"## Examples of supported options:","isFullCredit":false},{"lineNumber":5,"author":{"gitId":"-"},"content":"### ./get-reposense.py --release # Gets the latest release (Stable)","isFullCredit":false},{"lineNumber":6,"author":{"gitId":"-"},"content":"### ./get-reposense.py --master # Gets the latest master (Beta)","isFullCredit":false},{"lineNumber":7,"author":{"gitId":"-"},"content":"### ./get-reposense.py --tag v1.6.1 # Gets a specific version","isFullCredit":false},{"lineNumber":8,"author":{"gitId":"jedkohjk"},"content":"### ./get-reposense.py --latest v1.6 # Gets the latest version with the given tag prefix e.g. v1.6.1","isFullCredit":false},{"lineNumber":9,"author":{"gitId":"-"},"content":"### ./get-reposense.py --commit abc123 # Gets a specific commit","isFullCredit":false},{"lineNumber":10,"author":{"gitId":"-"},"content":"### ./get-reposense.py --release --overwrite # Overwrite RepoSense.jar, if exists, with the latest release","isFullCredit":false},{"lineNumber":11,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":12,"author":{"gitId":"-"},"content":"./get-reposense.py --release","isFullCredit":false},{"lineNumber":13,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":14,"author":{"gitId":"-"},"content":"# Executes RepoSense","isFullCredit":false},{"lineNumber":15,"author":{"gitId":"-"},"content":"# Do not change the default output folder name (reposense-report)","isFullCredit":false},{"lineNumber":16,"author":{"gitId":"-"},"content":"## Examples of other valid options; For more, please view the user guide","isFullCredit":false},{"lineNumber":17,"author":{"gitId":"-"},"content":"### java -jar RepoSense.jar --repos https://github.com/reposense/RepoSense.git","isFullCredit":false},{"lineNumber":18,"author":{"gitId":"-"},"content":"","isFullCredit":false},{"lineNumber":19,"author":{"gitId":"-"},"content":"java -jar RepoSense.jar --config ./configs","isFullCredit":false}],"authorContributionMap":{"jedkohjk":1,"-":18}}] diff --git a/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRangeWithShallowCloning/expected/reposense_publish-RepoSense_master/commits.json b/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRangeWithShallowCloning/expected/reposense_publish-RepoSense_master/commits.json new file mode 100644 index 0000000000..5cf4f434d4 --- /dev/null +++ b/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRangeWithShallowCloning/expected/reposense_publish-RepoSense_master/commits.json @@ -0,0 +1 @@ +{"authorDailyContributionsMap":{"jedkohjk":[{"date":"2024-08-02T00:00:00","commitResults":[{"hash":"80185806433b561004c3d0245997a77afcc674f3","isMergeCommit":false,"messageTitle":"Add flag to get the latest release from a specified major version (#12)","messageBody":"The `--tag` flag fetches the exact specified RepoSense version, but provides no way to fetch the latest release of a specified major version.\r\n\r\nLet\u0027s introduce the `--latest` or `-l` flag to get the latest release from a specified major version.","fileTypesAndContributionMap":{"other":{"insertions":25,"deletions":0}}}]},{"date":"2024-08-13T00:00:00","commitResults":[{"hash":"3a748c5843b273dafa3080956eb138093b4b58c9","isMergeCommit":false,"messageTitle":"Clarify description of --latest flag in run.sh (#13)","messageBody":"Information about the function of the `--latest` flag is unclear.\r\n\r\nLet\u0027s clarify the description of `--latest` flag in `run.sh`.\r\n","fileTypesAndContributionMap":{"other":{"insertions":1,"deletions":1}}}]}]},"authorFileTypeContributionMap":{"jedkohjk":{"code":0,"tests":0,"docs":0,"other":25}},"authorContributionVariance":{"jedkohjk":47.354168},"authorDisplayNameMap":{"jedkohjk":"jedkohjk"}} diff --git a/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRangeWithShallowCloning/expected/summary.json b/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRangeWithShallowCloning/expected/summary.json new file mode 100644 index 0000000000..74f359e2ca --- /dev/null +++ b/src/systemtest/resources/ReportConfigSystemTest/sinceBeginningDateRangeWithShallowCloning/expected/summary.json @@ -0,0 +1 @@ +{"reportGeneratedTime":"Wed, 9 Apr 2025 15:48:40 SGT","reportGenerationTime":" 4.64 second(s)","zoneId":"Asia/Singapore","reportTitle":"RepoSense Report","repos":[{"location":{"location":"https://github.com/reposense/publish-RepoSense.git","repoName":"publish-RepoSense","organization":"reposense","domainName":"github"},"branch":"master","displayName":"reposense/publish-RepoSense[master]","outputFolderName":"reposense_publish-RepoSense_master","sinceDate":"1970-01-01T07:30:00","untilDate":"2024-08-31T23:59:59"}],"errorSet":[],"sinceDate":"2024-08-02T00:00:00","untilDate":"2024-08-31T23:59:59","isSinceDateProvided":true,"isUntilDateProvided":true,"supportedDomainUrlMap":{"NOT_RECOGNIZED":{"BRANCH":"","REPO_URL":"UNSUPPORTED","BASE_URL":"UNSUPPORTED","HISTORY_PATH":"","COMMIT_PATH":"","BLAME_PATH":""},"github":{"BRANCH":"tree/$BRANCH","REPO_URL":"https://github.com/$ORGANIZATION/$REPO_NAME/","BASE_URL":"https://github.com/","HISTORY_PATH":"commits/$BRANCH/$FILE_PATH","COMMIT_PATH":"commit/$COMMIT_HASH","BLAME_PATH":"blame/$BRANCH/$FILE_PATH"}},"isAuthorshipAnalyzed":false,"repoBlurbs":{"blurbMap":{"https://github.com/reposense/publish-RepoSense/tree/master":"Publish branch of Reposense"}},"authorBlurbs":{"blurbMap":{}},"isPortfolio":false} diff --git a/src/test/java/reposense/model/OneStopConfigRunConfigurationTest.java b/src/test/java/reposense/model/OneStopConfigRunConfigurationTest.java new file mode 100644 index 0000000000..bba8a27fc5 --- /dev/null +++ b/src/test/java/reposense/model/OneStopConfigRunConfigurationTest.java @@ -0,0 +1,91 @@ +package reposense.model; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import reposense.model.reportconfig.ReportAuthorDetails; +import reposense.model.reportconfig.ReportBranchData; +import reposense.model.reportconfig.ReportConfiguration; +import reposense.model.reportconfig.ReportGroupNameAndGlobs; +import reposense.model.reportconfig.ReportRepoConfiguration; +import reposense.parser.exceptions.InvalidLocationException; + +class OneStopConfigRunConfigurationTest { + + private static CliArguments testSetUp; + private static List expectedRepoConfigurations; + + public static void setUpActualRepoConfigurations() { + CliArguments.Builder testCliBuilder = new CliArguments.Builder(); + + List globPatterns = List.of("**.java"); + List groups = List.of(new ReportGroupNameAndGlobs("code", globPatterns)); + + List emailList = List.of("fh@gmail.com"); + ReportAuthorDetails author = new ReportAuthorDetails(emailList, "FH-30", + "Francis Hodianto", "Francis Hodianto"); + + List authorList = List.of(author); + List ignoreGlobList = List.of("**.md"); + List ignoreAuthorList = List.of("bot"); + ReportBranchData branch = new ReportBranchData("master", "My project", authorList, + ignoreGlobList, ignoreAuthorList, 2000000L); + + List branches = List.of(branch); + ReportRepoConfiguration repo = new ReportRepoConfiguration("https://github.com/reposense/testrepo-Delta.git", + groups, branches); + + List repos = List.of(repo); + ReportConfiguration expectedReportConfig = new ReportConfiguration("Test RepoSense Report", repos); + testCliBuilder.reportConfiguration(expectedReportConfig); + testSetUp = testCliBuilder.build(); + } + + public static void setUpExpectedRepoConfigurations() throws InvalidLocationException { + expectedRepoConfigurations = new ArrayList<>(); + RepoLocation expectedRepoLocation = new RepoLocation("https://github.com/reposense/testrepo-Delta.git"); + List authorConfigs = new ArrayList<>(); + List groupConfigs = new ArrayList<>(); + + RepoConfiguration.Builder builder = new RepoConfiguration.Builder() + .location(expectedRepoLocation) + .branch("master") + .ignoreGlobList(List.of("**.md")) + .ignoredAuthorsList(List.of("bot")) + .fileSizeLimit(2000000L) + // Needs to be removed this when we deprecate the standalone config + .isStandaloneConfigIgnored(true); + + expectedRepoConfigurations.add(builder.build()); + + GroupConfiguration groupConfiguration = new GroupConfiguration(expectedRepoLocation); + groupConfiguration.addGroup(new FileType("code", List.of("**.java"))); + + groupConfigs.add(groupConfiguration); + + Author author = new Author("FH-30"); + author.setEmails(List.of("fh@gmail.com")); + author.setDisplayName("Francis Hodianto"); + author.setAuthorAliases(List.of("Francis Hodianto")); + + AuthorConfiguration authorConfiguration = new AuthorConfiguration(expectedRepoLocation, "master"); + authorConfiguration.addAuthor(author); + authorConfigs.add(authorConfiguration); + + RepoConfiguration.merge(expectedRepoConfigurations, authorConfigs); + RepoConfiguration.setGroupConfigsToRepos(expectedRepoConfigurations, groupConfigs); + } + + @Test + public void getRepoConfigurations_withValidInputs_returnsRepoConfigurations() throws InvalidLocationException { + setUpActualRepoConfigurations(); + setUpExpectedRepoConfigurations(); + + OneStopConfigRunConfiguration config = new OneStopConfigRunConfiguration(testSetUp); + List actualRepoConfigurations = config.getRepoConfigurations(); + Assertions.assertEquals(expectedRepoConfigurations, actualRepoConfigurations); + } +} diff --git a/src/test/java/reposense/model/RunConfigurationDeciderTest.java b/src/test/java/reposense/model/RunConfigurationDeciderTest.java index 66c9aa246d..f85d49c222 100644 --- a/src/test/java/reposense/model/RunConfigurationDeciderTest.java +++ b/src/test/java/reposense/model/RunConfigurationDeciderTest.java @@ -25,6 +25,13 @@ public class RunConfigurationDeciderTest { private static final Path PROJECT_DIRECTORY = Paths.get(System.getProperty("user.dir")); private static final Path CONFIG_FOLDER_ABSOLUTE = loadResource(ArgsParserTest.class, "cli_location_test"); + private static final Path ONLY_REPORT_CONFIG_TITLE_FOLDER = loadResource(RunConfigurationDeciderTest.class, + "RunConfigurationDeciderTest/only-report-config-title"); + private static final Path BOTH_CONFIGS_FOLDER = loadResource(RunConfigurationDeciderTest.class, + "RunConfigurationDeciderTest/both-configs"); + private static final Path NO_REPORT_CONFIG_FOLDER = loadResource(RunConfigurationDeciderTest.class, + "RunConfigurationDeciderTest/no-report-config"); + private static final String NONEXISTENT_DIRECTORY = "some_non_existent_dir/"; private static final InputBuilder DEFAULT_INPUT_BUILDER = new InputBuilder(); @@ -32,7 +39,6 @@ public class RunConfigurationDeciderTest { private static final String TEST_REPO_REPOSENSE = "https://github.com/reposense/RepoSense.git"; private static final String TEST_REPO_BETA = "https://github.com/reposense/testrepo-Beta.git"; - @BeforeEach public void before() { DEFAULT_INPUT_BUILDER.reset().addConfig(CONFIG_FOLDER_ABSOLUTE); @@ -70,10 +76,49 @@ public void parse_addRepos_returnsCliRunConfiguration() throws Exception { } @Test - public void parse_reposAndConfigNotSpecified_returnsConfigRunConfiguration() throws Exception { + public void parse_reposAndConfigNotSpecified_doesNotReturnCliRunConfiguration() throws Exception { + String input = new InputBuilder() + .addSinceDate("01/07/2017") + .addUntilDate("30/11/2017") + .addView() + .build(); + CliArguments cliArguments = ArgsParser.parse(translateCommandline(input)); + RunConfiguration runConfiguration = getRunConfiguration(cliArguments); + Assertions.assertFalse(runConfiguration instanceof CliRunConfiguration); + } + + @Test + public void parse_bothConfigsPresent_returnsOneStopConfigRunConfiguration() throws Exception { + String input = new InputBuilder() + .addSinceDate("01/07/2017") + .addUntilDate("30/11/2017") + .addConfig(BOTH_CONFIGS_FOLDER) + .addView() + .build(); + CliArguments cliArguments = ArgsParser.parse(translateCommandline(input)); + RunConfiguration runConfiguration = getRunConfiguration(cliArguments); + Assertions.assertTrue(runConfiguration instanceof OneStopConfigRunConfiguration); + } + + @Test + public void parse_reposAndConfigNotSpecifiedOnlyReportConfigTitle_returnsConfigRunConfiguration() throws Exception { + String input = new InputBuilder() + .addSinceDate("01/07/2017") + .addUntilDate("30/11/2017") + .addConfig(ONLY_REPORT_CONFIG_TITLE_FOLDER) + .addView() + .build(); + CliArguments cliArguments = ArgsParser.parse(translateCommandline(input)); + RunConfiguration runConfiguration = getRunConfiguration(cliArguments); + Assertions.assertTrue(runConfiguration instanceof ConfigRunConfiguration); + } + + @Test + public void parse_reposAndConfigNotSpecifiedNoReportConfig_returnsConfigRunConfiguration() throws Exception { String input = new InputBuilder() .addSinceDate("01/07/2017") .addUntilDate("30/11/2017") + .addConfig(NO_REPORT_CONFIG_FOLDER) .addView() .build(); CliArguments cliArguments = ArgsParser.parse(translateCommandline(input)); diff --git a/src/test/java/reposense/model/reportconfig/ReportAuthorDetailsTest.java b/src/test/java/reposense/model/reportconfig/ReportAuthorDetailsTest.java new file mode 100644 index 0000000000..c3d94913e9 --- /dev/null +++ b/src/test/java/reposense/model/reportconfig/ReportAuthorDetailsTest.java @@ -0,0 +1,77 @@ +package reposense.model.reportconfig; + +import java.util.List; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class ReportAuthorDetailsTest { + private static final ReportAuthorDetails details1 = new ReportAuthorDetails( + List.of("test@example.com"), + "gitHostId", + "Display Name", + "Git Author" + ); + + @Test + public void constructor_withValidInputs_success() { + List emails = List.of("test@example.com", "test2@example.com"); + ReportAuthorDetails details = new ReportAuthorDetails( + emails, + "Git Host Id", + "Display Name", + "Git Author" + ); + + Assertions.assertEquals(emails, details.getAuthorEmails()); + Assertions.assertEquals("Git Host Id", details.getAuthorGitHostId()); + Assertions.assertEquals("Display Name", details.getAuthorDisplayName()); + Assertions.assertEquals("Git Author", details.getAuthorGitAuthorName()); + } + + @Test + public void constructor_nullGitHostId_throwsIllegalArgumentException() { + Assertions.assertThrows(IllegalArgumentException.class, () -> { + new ReportAuthorDetails( + List.of("test@example.com"), + null, + "Display Name", + "Git Author" + ); + }); + } + + @Test + public void equals_sameObject_success() { + Assertions.assertEquals(details1, details1); + } + + @Test + public void equals_equivalentObject_success() { + ReportAuthorDetails details2 = new ReportAuthorDetails( + List.of("test@example.com"), + "gitHostId", + "Display Name", + "Git Author" + ); + + Assertions.assertEquals(details1, details2); + } + + @Test + public void equals_differentObject_failure() { + ReportAuthorDetails details2 = new ReportAuthorDetails( + List.of("test1@example.com"), + "gitHostId", + "Display Name", + "Git Author" + ); + + Assertions.assertNotEquals(details1, details2); + } + + @Test + public void equals_differentClass_failure() { + Assertions.assertNotEquals(details1, new Object()); + } +} diff --git a/src/test/java/reposense/model/reportconfig/ReportBranchDataTest.java b/src/test/java/reposense/model/reportconfig/ReportBranchDataTest.java new file mode 100644 index 0000000000..630a539884 --- /dev/null +++ b/src/test/java/reposense/model/reportconfig/ReportBranchDataTest.java @@ -0,0 +1,87 @@ +package reposense.model.reportconfig; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class ReportBranchDataTest { + private static final ReportBranchData data1 = new ReportBranchData( + "main", + "Test blurb", + null, + List.of("*.log"), + List.of("bot"), + 2000000L + ); + + @Test + public void constructor_withValidInputs_success() { + String branch = "main"; + String blurb = "Test blurb"; + List authors = null; + List ignoreGlobs = List.of("*.log"); + List ignoreAuthors = List.of("bot"); + Long fileSize = 2000000L; + + ReportBranchData data = new ReportBranchData(branch, blurb, authors, ignoreGlobs, ignoreAuthors, fileSize); + + Assertions.assertEquals(branch, data.getBranch()); + Assertions.assertEquals(blurb, data.getBlurb()); + Assertions.assertEquals(new ArrayList<>(), data.getReportAuthorDetails()); + Assertions.assertEquals(ignoreGlobs, data.getIgnoreGlobList()); + Assertions.assertEquals(ignoreAuthors, data.getIgnoreAuthorList()); + Assertions.assertEquals(fileSize, data.getFileSizeLimit()); + } + + @Test + public void constructor_withNullInputs_shouldUseDefaultValues() { + ReportBranchData data = new ReportBranchData(null, null, null, null, null, null); + + Assertions.assertEquals(ReportBranchData.DEFAULT_BRANCH, data.getBranch()); + Assertions.assertEquals("", data.getBlurb()); + Assertions.assertEquals(new ArrayList<>(), data.getReportAuthorDetails()); + Assertions.assertEquals(new ArrayList<>(), data.getIgnoreGlobList()); + Assertions.assertEquals(new ArrayList<>(), data.getIgnoreAuthorList()); + Assertions.assertEquals(ReportBranchData.DEFAULT_FILE_SIZE_LIMIT, data.getFileSizeLimit()); + } + + @Test + public void equals_sameObject_success() { + Assertions.assertEquals(data1, data1); + } + + @Test + public void equals_equivalentObject_success() { + ReportBranchData data2 = new ReportBranchData( + "main", + "Test blurb", + null, + List.of("*.log"), + List.of("bot"), + 2000000L + ); + + Assertions.assertEquals(data1, data2); + } + + @Test + public void equals_differentObject_failure() { + ReportBranchData data2 = new ReportBranchData( + "master", + "Test blurb", + null, + List.of("*.log"), + List.of("bot"), + 2000000L + ); + + Assertions.assertNotEquals(data1, data2); + } + + @Test + public void equals_differentClass_failure() { + Assertions.assertNotEquals(data1, new Object()); + } +} diff --git a/src/test/java/reposense/model/reportconfig/ReportConfigurationTest.java b/src/test/java/reposense/model/reportconfig/ReportConfigurationTest.java new file mode 100644 index 0000000000..29a7d6e4af --- /dev/null +++ b/src/test/java/reposense/model/reportconfig/ReportConfigurationTest.java @@ -0,0 +1,91 @@ +package reposense.model.reportconfig; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import reposense.model.RepoBlurbMap; + +public class ReportConfigurationTest { + + private static ReportConfiguration expectedReportConfig; + private static ReportConfiguration invalidReportConfig; + + @BeforeAll + public static void setUp() { + List globPatterns = List.of("**.java"); + List groups = List.of(new ReportGroupNameAndGlobs("code", globPatterns)); + + List emailList = List.of("fh@gmail.com"); + ReportAuthorDetails author = new ReportAuthorDetails(emailList, "FH-30", + "Francis Hodianto", "Francis Hodianto"); + + List authorList = List.of(author); + List ignoreGlobList = List.of("**.md"); + List ignoreAuthorList = List.of("bot"); + ReportBranchData branch = new ReportBranchData("master", "My project", authorList, + ignoreGlobList, ignoreAuthorList, 2000000L); + + List branches = List.of(branch); + ReportRepoConfiguration repo = new ReportRepoConfiguration("https://github.com/reposense/testrepo-Delta.git", + groups, branches); + + List repos = List.of(repo); + expectedReportConfig = new ReportConfiguration("Test RepoSense Report", repos); + + // Invalid repo with missing .git + ReportRepoConfiguration invalidRepo = new ReportRepoConfiguration("https://github.com/reposense/testrepo-Delta", + groups, branches); + + List invalidRepos = List.of(invalidRepo); + invalidReportConfig = new ReportConfiguration("Test RepoSense Report", invalidRepos); + } + + @Test + public void constructor_withValidInputs_success() { + ReportConfiguration reportConfiguration = new ReportConfiguration("My Report", new ArrayList<>()); + Assertions.assertNotNull(reportConfiguration); + } + + @Test + public void getTitle_equalsDefaultReturnValue_success() { + Assertions.assertSame(ReportConfiguration.DEFAULT_TITLE, + new ReportConfiguration(null, null).getTitle()); + } + + @Test + public void getBlurbMap_withValidInputs_success() { + RepoBlurbMap expectedBlurbMap = new RepoBlurbMap(); + expectedBlurbMap.withRecord("https://github.com/reposense/testrepo-Delta/tree/master", "My project"); + + Assertions.assertEquals(expectedBlurbMap, expectedReportConfig.getRepoBlurbMap()); + } + + @Test + public void getBlurbMap_withInvalidInputs_returnEmptyBlurbMap() { + RepoBlurbMap expectedBlurbMap = new RepoBlurbMap(); + expectedBlurbMap.withRecord("https://github.com/reposense/testrepo-Delta/tree/master", "My project"); + + Assertions.assertNotEquals(expectedBlurbMap, invalidReportConfig.getRepoBlurbMap()); + Assertions.assertEquals(new RepoBlurbMap(), invalidReportConfig.getRepoBlurbMap()); + } + + @Test + public void equals_withSameObject_success() { + Assertions.assertEquals(expectedReportConfig, expectedReportConfig); + } + + @Test + public void equals_withDifferentObject_failure() { + Assertions.assertNotEquals(new ReportConfiguration(null, null), expectedReportConfig); + } + + @Test + public void equals_differentClass_failure() { + Assertions.assertNotEquals(expectedReportConfig, new Object()); + } + +} diff --git a/src/test/java/reposense/model/reportconfig/ReportGroupNameAndGlobsTest.java b/src/test/java/reposense/model/reportconfig/ReportGroupNameAndGlobsTest.java new file mode 100644 index 0000000000..f564c66d32 --- /dev/null +++ b/src/test/java/reposense/model/reportconfig/ReportGroupNameAndGlobsTest.java @@ -0,0 +1,57 @@ +package reposense.model.reportconfig; + +import java.util.List; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import reposense.model.FileType; + +public class ReportGroupNameAndGlobsTest { + private static final ReportGroupNameAndGlobs reportGroupNameAndGlobs1 = new ReportGroupNameAndGlobs("My Group", + List.of("code")); + + @Test + public void constructor_withValidInputs_success() { + Assertions.assertNotNull(reportGroupNameAndGlobs1); + Assertions.assertEquals("My Group", reportGroupNameAndGlobs1.getGroupName()); + Assertions.assertEquals(List.of("code"), reportGroupNameAndGlobs1.getGlobs()); + } + + @Test + public void constructor_nullGroupName_throwsIllegalArgumentException() { + Assertions.assertThrows(IllegalArgumentException.class, () -> new ReportGroupNameAndGlobs(null, + List.of("code"))); + } + + @Test + public void constructor_nullGlobs_throwsIllegalArgumentException() { + Assertions.assertThrows(IllegalArgumentException.class, () -> new ReportGroupNameAndGlobs("My Group", null)); + } + + @Test + public void constructor_nullGroupNameAndNullGlobs_throwsIllegalArgumentException() { + Assertions.assertThrows(IllegalArgumentException.class, () -> new ReportGroupNameAndGlobs(null, null)); + } + + @Test + public void toFileType_success() { + Assertions.assertEquals(new FileType("My Group", List.of("code")), reportGroupNameAndGlobs1.toFileType()); + } + + @Test + public void equals_sameObject_success() { + Assertions.assertEquals(reportGroupNameAndGlobs1, reportGroupNameAndGlobs1); + } + + @Test + public void equals_differentObject_failure() { + ReportGroupNameAndGlobs reportGroupNameAndGlobs2 = new ReportGroupNameAndGlobs("My Group", List.of("test")); + Assertions.assertNotEquals(reportGroupNameAndGlobs1, reportGroupNameAndGlobs2); + } + + @Test + public void equals_differentClass_failure() { + Assertions.assertNotEquals(reportGroupNameAndGlobs1, new Object()); + } +} diff --git a/src/test/java/reposense/model/reportconfig/ReportRepoConfigurationTest.java b/src/test/java/reposense/model/reportconfig/ReportRepoConfigurationTest.java new file mode 100644 index 0000000000..f2cfdb3850 --- /dev/null +++ b/src/test/java/reposense/model/reportconfig/ReportRepoConfigurationTest.java @@ -0,0 +1,105 @@ +package reposense.model.reportconfig; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import reposense.model.FileType; +import reposense.model.GroupConfiguration; +import reposense.model.RepoLocation; +import reposense.parser.exceptions.InvalidLocationException; + +public class ReportRepoConfigurationTest { + private static final List groups = List.of( + new ReportGroupNameAndGlobs("group1", List.of("glob1", "glob2")), + new ReportGroupNameAndGlobs("group2", List.of("glob3", "glob4")) + ); + + @Test + void constructor_nullRepo_throwsIllegalArgumentException() { + Assertions.assertThrows(IllegalArgumentException.class, () -> + new ReportRepoConfiguration(null, null, null)); + } + + @Test + void constructor_nullGroupsAndBranches_createsEmptyLists() { + ReportRepoConfiguration config = new ReportRepoConfiguration("https://github.com/test/repo.git", null, null); + + Assertions.assertNotNull(config.getGroupDetails()); + Assertions.assertTrue(config.getGroupDetails().isEmpty()); + Assertions.assertNotNull(config.getBranches()); + Assertions.assertTrue(config.getBranches().isEmpty()); + } + + @Test + void getFullyQualifiedRepoNamesWithBlurbs_validUrl_returnsCorrectMapping() { + List branches = List.of( + new ReportBranchData("main", "Main branch", null, null, null, null), + new ReportBranchData("dev", "Development branch", null, null, null, null) + ); + ReportRepoConfiguration config = new ReportRepoConfiguration( + "https://github.com/test/repo.git", + new ArrayList<>(), + branches + ); + + List result = config.getFullyQualifiedRepoNamesWithBlurbs(); + + Assertions.assertEquals(2, result.size()); + Assertions.assertEquals("https://github.com/test/repo/tree/main", result.get(0).getKey()); + Assertions.assertEquals("Main branch", result.get(0).getValue()); + Assertions.assertEquals("https://github.com/test/repo/tree/dev", result.get(1).getKey()); + Assertions.assertEquals("Development branch", result.get(1).getValue()); + } + + @Test + void getFullyQualifiedRepoNamesWithBlurbs_invalidUrl_throwsIllegalArgumentException() { + ReportRepoConfiguration config = new ReportRepoConfiguration( + "https://github.com/test/repo", // Missing .git + null, + null + ); + + Assertions.assertThrows(IllegalArgumentException.class, () -> config.getFullyQualifiedRepoNamesWithBlurbs()); + } + + @Test + void getGroupConfiguration_validGroups_returnsCorrectMapping() throws InvalidLocationException { + ReportRepoConfiguration config = new ReportRepoConfiguration( + "https://github.com/test/repo.git", groups, null); + + RepoLocation repoLocation = new RepoLocation("https://github.com/test/repo.git"); + GroupConfiguration expectedGroupConfiguration = new GroupConfiguration(repoLocation); + expectedGroupConfiguration.addGroup(new FileType("group1", List.of("glob1", "glob2"))); + expectedGroupConfiguration.addGroup(new FileType("group2", List.of("glob3", "glob4"))); + + Assertions.assertEquals(expectedGroupConfiguration, + config.getGroupConfiguration(new RepoLocation("https://github.com/test/repo.git"))); + } + + @Test + void equals_sameObject_success() { + ReportRepoConfiguration config = new ReportRepoConfiguration( + "https://github.com/test/repo.git", groups, null); + + Assertions.assertEquals(config, config); + } + + @Test + void equals_differentObject_failure() { + ReportRepoConfiguration config1 = new ReportRepoConfiguration( + "https://github.com/dev/repo.git", groups, null); + ReportRepoConfiguration config2 = new ReportRepoConfiguration( + "https://github.com/test/repo.git", groups, null); + + Assertions.assertNotEquals(config1, config2); + } + + @Test + public void equals_differentClass_failure() { + Assertions.assertNotEquals(new ReportRepoConfiguration( + "https://github.com/dev/repo.git", groups, null), new Object()); + } +} diff --git a/src/test/java/reposense/parser/ReportConfigJsonParserTest.java b/src/test/java/reposense/parser/ReportConfigJsonParserTest.java deleted file mode 100644 index 44005ad8d2..0000000000 --- a/src/test/java/reposense/parser/ReportConfigJsonParserTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package reposense.parser; - -import static reposense.util.TestUtil.loadResource; - -import java.nio.file.Path; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import reposense.model.ReportConfiguration; - -public class ReportConfigJsonParserTest { - - private static final Path VALID_REPORT_CONFIG = loadResource( - ReportConfigJsonParserTest.class, "ReportConfigJsonParserTest/report-config-valid.json"); - private static final Path INVALID_REPORT_CONFIG = loadResource( - ReportConfigJsonParserTest.class, "ReportConfigJsonParserTest/report-config-invalid.json"); - private static final Path EMPTY_REPORT_CONFIG = loadResource( - ReportConfigJsonParserTest.class, "ReportConfigJsonParserTest/report-config-empty.json"); - private static final String DEFAULT_TITLE = "RepoSense Report"; - - @Test - public void reportConfig_parseEmptyJsonFile_getDefaultTitle() throws Exception { - ReportConfiguration reportConfig = new ReportConfigJsonParser().parse(EMPTY_REPORT_CONFIG); - Assertions.assertEquals(reportConfig.getTitle(), DEFAULT_TITLE); - } - @Test - public void reportConfig_parseInvalidJsonFile_getDefaultTitle() throws Exception { - ReportConfiguration reportConfig = new ReportConfigJsonParser().parse(INVALID_REPORT_CONFIG); - Assertions.assertEquals(reportConfig.getTitle(), DEFAULT_TITLE); - } - - @Test - public void reportConfig_parseValidJsonFile_getCustomTitle() throws Exception { - ReportConfiguration reportConfig = new ReportConfigJsonParser().parse(VALID_REPORT_CONFIG); - Assertions.assertNotEquals(reportConfig.getTitle(), DEFAULT_TITLE); - } -} diff --git a/src/test/java/reposense/parser/ReportConfigYamlParserTest.java b/src/test/java/reposense/parser/ReportConfigYamlParserTest.java new file mode 100644 index 0000000000..dbb7dfaef4 --- /dev/null +++ b/src/test/java/reposense/parser/ReportConfigYamlParserTest.java @@ -0,0 +1,82 @@ +package reposense.parser; + +import static reposense.util.TestUtil.loadResource; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import reposense.model.reportconfig.ReportAuthorDetails; +import reposense.model.reportconfig.ReportBranchData; +import reposense.model.reportconfig.ReportConfiguration; +import reposense.model.reportconfig.ReportGroupNameAndGlobs; +import reposense.model.reportconfig.ReportRepoConfiguration; + +public class ReportConfigYamlParserTest { + + private static final Path VALID_REPORT_CONFIG = loadResource( + ReportConfigYamlParserTest.class, "ReportConfigYamlParserTest/report-config-valid.yaml"); + private static final Path INVALID_REPORT_CONFIG = loadResource( + ReportConfigYamlParserTest.class, "ReportConfigYamlParserTest/report-config-invalid.yaml"); + private static final Path EMPTY_REPORT_CONFIG = loadResource( + ReportConfigYamlParserTest.class, "ReportConfigYamlParserTest/report-config-empty.yaml"); + + private static ReportConfiguration expectedReportConfig; + + @BeforeAll + public static void setUp() { + List groups = new ArrayList<>(); + List globPatterns = new ArrayList<>(); + globPatterns.add("**.java"); + groups.add(new ReportGroupNameAndGlobs("code", globPatterns)); + + List emailList = new ArrayList<>(); + emailList.add("fh@gmail.com"); + ReportAuthorDetails author = new ReportAuthorDetails(emailList, "FH-30", + "Francis Hodianto", "Francis Hodianto"); + + List authorList = new ArrayList<>(); + authorList.add(author); + List ignoreGlobList = new ArrayList<>(); + ignoreGlobList.add("**.md"); + List ignoreAuthorList = new ArrayList<>(); + ignoreAuthorList.add("bot"); + + ReportBranchData branch = new ReportBranchData("master", "My project", authorList, + ignoreGlobList, ignoreAuthorList, 2000000L); + List branches = new ArrayList<>(); + branches.add(branch); + + ReportRepoConfiguration repo = new ReportRepoConfiguration("https://github.com/reposense/testrepo-Delta.git", + groups, branches); + List repos = new ArrayList<>(); + repos.add(repo); + + expectedReportConfig = new ReportConfiguration("Test RepoSense Report", repos); + } + + @Test + public void reportConfig_parseEmptyYamlFile_throwsIoException() { + Assertions.assertThrows(Exception.class, () -> new ReportConfigYamlParser().parse(EMPTY_REPORT_CONFIG)); + } + + @Test + public void reportConfig_parseInvalidYamlFile_throwsIoException() { + Assertions.assertThrows(Exception.class, () -> new ReportConfigYamlParser().parse(INVALID_REPORT_CONFIG)); + } + + @Test + public void reportConfig_parseValidYamlFile_success() throws Exception { + ReportConfiguration reportConfig = new ReportConfigYamlParser().parse(VALID_REPORT_CONFIG); + Assertions.assertEquals(expectedReportConfig, reportConfig); + } + + @Test + public void getType_validType_success() { + Assertions.assertEquals(ReportConfiguration.class, new ReportConfigYamlParser().getType()); + } +} diff --git a/src/test/java/reposense/parser/SummaryJsonParserTest.java b/src/test/java/reposense/parser/SummaryJsonParserTest.java index ce65497024..f78db02a03 100644 --- a/src/test/java/reposense/parser/SummaryJsonParserTest.java +++ b/src/test/java/reposense/parser/SummaryJsonParserTest.java @@ -19,7 +19,6 @@ import reposense.model.RepoBlurbMap; import reposense.model.RepoConfiguration; import reposense.model.RepoLocation; -import reposense.model.ReportConfiguration; import reposense.report.SummaryJson; public class SummaryJsonParserTest { @@ -37,7 +36,7 @@ public static void setUp() throws Exception { String reportGenerationTime = " 1 minute(s) 19.83 second(s)"; String repoSenseVersion = "48a60d6c0d"; ZoneId zoneId = ZoneId.of("Asia/Singapore"); - ReportConfiguration reportConfig = new ReportConfiguration(); + String reportTitle = "RepoSense Report"; LocalDateTime sinceDate = LocalDate.parse("2025-02-16").atStartOfDay(); LocalDateTime untilDate = LocalDateTime.parse("2025-03-16T23:59:59"); boolean isSinceDateProvided = false; @@ -68,7 +67,7 @@ public static void setUp() throws Exception { AuthorBlurbMap authorBlurbs = new AuthorBlurbMap(); authorBlurbs.withRecord("nbriannl", "Test for author-blurbs.md"); - expectedValidSummaryJson = new SummaryJson(repos, reportConfig, reportGeneratedTime, sinceDate, untilDate, + expectedValidSummaryJson = new SummaryJson(repos, reportTitle, reportGeneratedTime, sinceDate, untilDate, isSinceDateProvided, isUntilDateProvided, repoSenseVersion, errorSet, reportGenerationTime, zoneId, isAuthorshipAnalyzed, repoBlurbs, authorBlurbs, isPortfolio); } @@ -101,14 +100,13 @@ public void summaryJson_parseValidJsonFile_success() throws Exception { .build(); SummaryJson actualSummaryJson = new SummaryJson(List.of(repoConfig), - new ReportConfiguration(parsedSummaryJson.getReportTitle()), - parsedSummaryJson.getReportGeneratedTime(), parsedSummaryJson.getSinceDate(), - parsedSummaryJson.getUntilDate(), parsedSummaryJson.isSinceDateProvided(), - parsedSummaryJson.isUntilDateProvided(), parsedSummaryJson.getRepoSenseVersion(), - parsedSummaryJson.getErrorSet(), parsedSummaryJson.getReportGenerationTime(), - parsedSummaryJson.getZoneId(), parsedSummaryJson.isAuthorshipAnalyzed(), - parsedSummaryJson.getRepoBlurbs(), parsedSummaryJson.getAuthorBlurbs(), - parsedSummaryJson.isPortfolio()); + parsedSummaryJson.getReportTitle(), parsedSummaryJson.getReportGeneratedTime(), + parsedSummaryJson.getSinceDate(), parsedSummaryJson.getUntilDate(), + parsedSummaryJson.isSinceDateProvided(), parsedSummaryJson.isUntilDateProvided(), + parsedSummaryJson.getRepoSenseVersion(), parsedSummaryJson.getErrorSet(), + parsedSummaryJson.getReportGenerationTime(), parsedSummaryJson.getZoneId(), + parsedSummaryJson.isAuthorshipAnalyzed(), parsedSummaryJson.getRepoBlurbs(), + parsedSummaryJson.getAuthorBlurbs(), parsedSummaryJson.isPortfolio()); Assertions.assertEquals(expectedValidSummaryJson, actualSummaryJson); } diff --git a/src/test/java/reposense/report/ReportGeneratorTest.java b/src/test/java/reposense/report/ReportGeneratorTest.java index 1cf1049e1b..c4069ff227 100644 --- a/src/test/java/reposense/report/ReportGeneratorTest.java +++ b/src/test/java/reposense/report/ReportGeneratorTest.java @@ -21,7 +21,7 @@ import reposense.model.AuthorBlurbMap; import reposense.model.RepoBlurbMap; -import reposense.model.ReportConfiguration; +import reposense.model.reportconfig.ReportConfiguration; import reposense.parser.SummaryJsonParser; import reposense.util.TimeUtil; diff --git a/src/test/java/reposense/report/SummaryJsonTest.java b/src/test/java/reposense/report/SummaryJsonTest.java index 01cf0b59bc..38743cf533 100644 --- a/src/test/java/reposense/report/SummaryJsonTest.java +++ b/src/test/java/reposense/report/SummaryJsonTest.java @@ -20,8 +20,8 @@ import reposense.model.RepoBlurbMap; import reposense.model.RepoConfiguration; import reposense.model.RepoLocation; -import reposense.model.ReportConfiguration; import reposense.model.SupportedDomainUrlMap; +import reposense.model.reportconfig.ReportConfiguration; import reposense.parser.SummaryJsonParserTest; public class SummaryJsonTest { diff --git a/src/test/resources/ReportConfigJsonParserTest/report-config-empty.json b/src/test/resources/ReportConfigJsonParserTest/report-config-empty.json deleted file mode 100644 index 0db3279e44..0000000000 --- a/src/test/resources/ReportConfigJsonParserTest/report-config-empty.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - -} diff --git a/src/test/resources/ReportConfigJsonParserTest/report-config-invalid.json b/src/test/resources/ReportConfigJsonParserTest/report-config-invalid.json deleted file mode 100644 index fd26202fa2..0000000000 --- a/src/test/resources/ReportConfigJsonParserTest/report-config-invalid.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "ti": "!@#$%^&*()<>:" -} diff --git a/src/test/resources/ReportConfigJsonParserTest/report-config-valid.json b/src/test/resources/ReportConfigJsonParserTest/report-config-valid.json deleted file mode 100644 index ba731c2add..0000000000 --- a/src/test/resources/ReportConfigJsonParserTest/report-config-valid.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "title": "!@#$%^&*()<>:" -} diff --git a/src/test/resources/ReportConfigYamlParserTest/report-config-empty.yaml b/src/test/resources/ReportConfigYamlParserTest/report-config-empty.yaml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/test/resources/ReportConfigYamlParserTest/report-config-invalid.yaml b/src/test/resources/ReportConfigYamlParserTest/report-config-invalid.yaml new file mode 100644 index 0000000000..ea5be78365 --- /dev/null +++ b/src/test/resources/ReportConfigYamlParserTest/report-config-invalid.yaml @@ -0,0 +1,24 @@ +title: RepoSense Report +repos: + - repo: https://github.com/reposense/testrepo-Delta.git + groups: + - group-name: code + globs: + - "**.java" + - group-name: tests + globs: + - "src/test**" + - group-name: docs + globs: + - "docs**" + - "**.adoc" + - "**.md" + branches: + - branch: master + blurb: "My project" + aut:::thors: + - author-git-host-id: FH-30 + author-display-name: Francis Hodianto + author-git-author-name: Francis Hodianto + author-emails: + ignore-authors-list: diff --git a/src/test/resources/ReportConfigYamlParserTest/report-config-valid.yaml b/src/test/resources/ReportConfigYamlParserTest/report-config-valid.yaml new file mode 100644 index 0000000000..f9c2e7e454 --- /dev/null +++ b/src/test/resources/ReportConfigYamlParserTest/report-config-valid.yaml @@ -0,0 +1,22 @@ +title: Test RepoSense Report +repos: + - repo: https://github.com/reposense/testrepo-Delta.git + groups: + - group-name: code + globs: + - "**.java" + branches: + - branch: master + blurb: "My project" + authors: + - author-git-host-id: FH-30 + author-display-name: Francis Hodianto + author-git-author-name: Francis Hodianto + author-emails: + - fh@gmail.com + ignore-authors-list: + - bot + ignore-glob-list: + - "**.md" + file-size-limit: 2000000 + diff --git a/src/test/resources/RunConfigurationDeciderTest/both-configs/repo-config.csv b/src/test/resources/RunConfigurationDeciderTest/both-configs/repo-config.csv new file mode 100644 index 0000000000..4254328db4 --- /dev/null +++ b/src/test/resources/RunConfigurationDeciderTest/both-configs/repo-config.csv @@ -0,0 +1,4 @@ +Repository's Location,Branch,File formats,Ignore Glob List,Ignore standalone config,Ignore Commits List,Ignore Authors List,Shallow Cloning,Find Previous Authors,Since Date,Until Date +https://github.com/reposense/testrepo-Alpha.git,master,,,,2fb6b9b2dd9fa40bf0f9815da2cb0ae8731436c7;c5a6dc774e22099cd9ddeb0faff1e75f9cf4f151;cd7f610e0becbdf331d5231887d8010a689f87c7;768015345e70f06add2a8b7d1f901dc07bf70582,,,,, +https://github.com/reposense/testrepo-Beta.git,master,fxml,docs**,yes,,,,,, +https://github.com/reposense/testrepo-Beta.git,add-config-json,fxml,docs**,yes,,,,,, diff --git a/src/test/resources/RunConfigurationDeciderTest/both-configs/report-config.yaml b/src/test/resources/RunConfigurationDeciderTest/both-configs/report-config.yaml new file mode 100644 index 0000000000..100008bfa7 --- /dev/null +++ b/src/test/resources/RunConfigurationDeciderTest/both-configs/report-config.yaml @@ -0,0 +1,28 @@ +title: RepoSense Report +repos: + - repo: https://github.com/reposense/publish-RepoSense.git + groups: + - group-name: code + globs: + - "**.py" + - group-name: tests + globs: + - "src/test**" + - group-name: docs + globs: + - "docs**" + - "**.adoc" + - "**.md" + branches: + - branch: master + blurb: "My project" + authors: + - author-git-host-id: jedkohjk + author-display-name: jedkohjk + author-git-author-name: jedkohjk + author-emails: + ignore-authors-list: + - bot + ignore-glob-list: + - "**.in" + file-size-limit: 2000000 diff --git a/src/test/resources/RunConfigurationDeciderTest/no-report-config/repo-config.csv b/src/test/resources/RunConfigurationDeciderTest/no-report-config/repo-config.csv new file mode 100644 index 0000000000..4254328db4 --- /dev/null +++ b/src/test/resources/RunConfigurationDeciderTest/no-report-config/repo-config.csv @@ -0,0 +1,4 @@ +Repository's Location,Branch,File formats,Ignore Glob List,Ignore standalone config,Ignore Commits List,Ignore Authors List,Shallow Cloning,Find Previous Authors,Since Date,Until Date +https://github.com/reposense/testrepo-Alpha.git,master,,,,2fb6b9b2dd9fa40bf0f9815da2cb0ae8731436c7;c5a6dc774e22099cd9ddeb0faff1e75f9cf4f151;cd7f610e0becbdf331d5231887d8010a689f87c7;768015345e70f06add2a8b7d1f901dc07bf70582,,,,, +https://github.com/reposense/testrepo-Beta.git,master,fxml,docs**,yes,,,,,, +https://github.com/reposense/testrepo-Beta.git,add-config-json,fxml,docs**,yes,,,,,, diff --git a/src/test/resources/RunConfigurationDeciderTest/only-report-config-title/repo-config.csv b/src/test/resources/RunConfigurationDeciderTest/only-report-config-title/repo-config.csv new file mode 100644 index 0000000000..4254328db4 --- /dev/null +++ b/src/test/resources/RunConfigurationDeciderTest/only-report-config-title/repo-config.csv @@ -0,0 +1,4 @@ +Repository's Location,Branch,File formats,Ignore Glob List,Ignore standalone config,Ignore Commits List,Ignore Authors List,Shallow Cloning,Find Previous Authors,Since Date,Until Date +https://github.com/reposense/testrepo-Alpha.git,master,,,,2fb6b9b2dd9fa40bf0f9815da2cb0ae8731436c7;c5a6dc774e22099cd9ddeb0faff1e75f9cf4f151;cd7f610e0becbdf331d5231887d8010a689f87c7;768015345e70f06add2a8b7d1f901dc07bf70582,,,,, +https://github.com/reposense/testrepo-Beta.git,master,fxml,docs**,yes,,,,,, +https://github.com/reposense/testrepo-Beta.git,add-config-json,fxml,docs**,yes,,,,,, diff --git a/src/test/resources/RunConfigurationDeciderTest/only-report-config-title/report-config.yaml b/src/test/resources/RunConfigurationDeciderTest/only-report-config-title/report-config.yaml new file mode 100644 index 0000000000..a530aa7a91 --- /dev/null +++ b/src/test/resources/RunConfigurationDeciderTest/only-report-config-title/report-config.yaml @@ -0,0 +1 @@ +title: RepoSense Report