From f3db47a620829cf3d333079afe37f9487281dcd2 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Mon, 30 May 2022 18:42:18 +0530 Subject: [PATCH 001/146] Init git maintenance --- src/main/java/hudson/plugins/git/GitSCM.java | 2 +- .../git/maintenance/MaintenanceUI.java | 40 +++++++++++++++ .../git/maintenance/MaintenanceUI/index.jelly | 7 +++ src/main/webapp/icons/git-maintenance.svg | 51 +++++++++++++++++++ 4 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java create mode 100644 src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly create mode 100644 src/main/webapp/icons/git-maintenance.svg diff --git a/src/main/java/hudson/plugins/git/GitSCM.java b/src/main/java/hudson/plugins/git/GitSCM.java index a26f51363b..a3b18b65fa 100644 --- a/src/main/java/hudson/plugins/git/GitSCM.java +++ b/src/main/java/hudson/plugins/git/GitSCM.java @@ -304,7 +304,7 @@ public Object readResolve() throws IOException { if (remoteRepositories != null && userRemoteConfigs == null) { userRemoteConfigs = new ArrayList<>(); for(RemoteConfig cfg : remoteRepositories) { - // converted as in config.jelly + // converted as in index.jelly String url = ""; if (cfg.getURIs().size() > 0 && cfg.getURIs().get(0) != null) url = cfg.getURIs().get(0).toPrivateString(); diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java new file mode 100644 index 0000000000..d3438285e8 --- /dev/null +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -0,0 +1,40 @@ +package jenkins.plugins.git.maintenance; + +import edu.umd.cs.findbugs.annotations.NonNull; +import hudson.Extension; +import hudson.model.ManagementLink; + +@Extension +public class MaintenanceUI extends ManagementLink { + + @Override + public String getIconFileName() { + return jenkins.model.Jenkins.RESOURCE_PATH + "/plugin/git/icons/git-maintenance.svg"; + } + + @Override + public String getDisplayName() { + return "Git Maintenance"; + } + + @Override + public String getUrlName() { + return "maintenance"; + } + + @Override + public String getDescription() { + return "Maintain your Repositories to improve git command performance."; + } + + public @NonNull String getCategoryName() { + return "CONFIGURATION"; + } +// +// @NonNull +// @Override +// public Permission getRequiredPermission() { +// return Jenkins.ADMINISTER; +// } +// +} diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly new file mode 100644 index 0000000000..5a4f349786 --- /dev/null +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/main/webapp/icons/git-maintenance.svg b/src/main/webapp/icons/git-maintenance.svg new file mode 100644 index 0000000000..66ab7a3350 --- /dev/null +++ b/src/main/webapp/icons/git-maintenance.svg @@ -0,0 +1,51 @@ + + + + +Created by potrace 1.15, written by Peter Selinger 2001-2017 + + + + + From ae4b0666cd4bcba76684f1dd8726380ec9868a39 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Wed, 1 Jun 2022 03:39:59 +0530 Subject: [PATCH 002/146] Added basic layout --- .../git/maintenance/MaintenanceUI.java | 40 +++++++++++++++++++ .../plugins/git/maintenance/TaskData.java | 21 ++++++++++ .../git/maintenance/MaintenanceUI/index.jelly | 23 ++++++++++- 3 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 src/main/java/jenkins/plugins/git/maintenance/TaskData.java diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index d3438285e8..9642d2f08d 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -3,6 +3,14 @@ import edu.umd.cs.findbugs.annotations.NonNull; import hudson.Extension; import hudson.model.ManagementLink; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; +import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.interceptor.RequirePOST; + +import java.io.IOException; +import java.util.ArrayList; @Extension public class MaintenanceUI extends ManagementLink { @@ -30,6 +38,38 @@ public String getDescription() { public @NonNull String getCategoryName() { return "CONFIGURATION"; } + + @RequirePOST + @Restricted(NoExternalUse.class) + public void doSave(StaplerRequest req, StaplerResponse res) throws IOException { + System.out.println("Saving"); + res.sendRedirect(""); + } + + @RequirePOST + @Restricted(NoExternalUse.class) + public void doExecute(StaplerRequest req, StaplerResponse res) throws IOException { + System.out.println("Executing..."); + res.sendRedirect(""); + } + + @RequirePOST + @Restricted(NoExternalUse.class) + public void doTerminate(StaplerRequest req, StaplerResponse res) throws IOException { + System.out.println("Stopping..."); + res.sendRedirect(""); + } + + public ArrayList getMaintenanceTask(){ + // Can check if git version doesn't support a maintenance task and remove that maintenance task form the UI. + ArrayList tasks = new ArrayList(); + tasks.add(new TaskData("gc","Click to view gc")); + tasks.add(new TaskData("commit-graph","Click to view commit graph")); + tasks.add(new TaskData("incremental-repack","Click to view Incremental Repack")); + tasks.add(new TaskData("prefetch","Click to view prefetch")); + tasks.add(new TaskData("loose-objects","Click to view loose objects")); + return tasks; + } // // @NonNull // @Override diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskData.java b/src/main/java/jenkins/plugins/git/maintenance/TaskData.java new file mode 100644 index 0000000000..4d1a321478 --- /dev/null +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskData.java @@ -0,0 +1,21 @@ +package jenkins.plugins.git.maintenance; + +public class TaskData { + + String task; + String msg; + + public TaskData(String task, String msg){ + this.task = task; + this.msg = msg; + } + + public String getTaskName(){ + return this.task; + } + + public String getTaskMessage(){ + return this.msg; + } + +} diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly index 5a4f349786..8b470e8e4e 100644 --- a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly @@ -1,7 +1,28 @@ - + +
+

Maintenace Tasks

+

Enter cron syntax for periodic execution of maintenance tasks

+ + + + + + + + + + + + + + + + +
From c1b2d5c7b4fdab8d7d02198b309321c0a1f47f7c Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Wed, 1 Jun 2022 20:17:21 +0530 Subject: [PATCH 003/146] Added help files --- .../git/maintenance/MaintenanceUI/help-commit-graph.html | 3 +++ .../jenkins/plugins/git/maintenance/MaintenanceUI/help-gc.html | 3 +++ .../git/maintenance/MaintenanceUI/help-incremental-repack.html | 3 +++ .../git/maintenance/MaintenanceUI/help-loose-objects.html | 3 +++ .../plugins/git/maintenance/MaintenanceUI/help-prefetch.html | 3 +++ .../jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly | 2 +- 6 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/help-commit-graph.html create mode 100644 src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/help-gc.html create mode 100644 src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/help-incremental-repack.html create mode 100644 src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/help-loose-objects.html create mode 100644 src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/help-prefetch.html diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/help-commit-graph.html b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/help-commit-graph.html new file mode 100644 index 0000000000..50fe86c862 --- /dev/null +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/help-commit-graph.html @@ -0,0 +1,3 @@ +
+ Help regarding commit graph +
\ No newline at end of file diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/help-gc.html b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/help-gc.html new file mode 100644 index 0000000000..b0ad57c725 --- /dev/null +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/help-gc.html @@ -0,0 +1,3 @@ +
+ Help regarding gc +
diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/help-incremental-repack.html b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/help-incremental-repack.html new file mode 100644 index 0000000000..f4feaf18a4 --- /dev/null +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/help-incremental-repack.html @@ -0,0 +1,3 @@ +
+ Help regarding incremental repack +
\ No newline at end of file diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/help-loose-objects.html b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/help-loose-objects.html new file mode 100644 index 0000000000..71d2dc5714 --- /dev/null +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/help-loose-objects.html @@ -0,0 +1,3 @@ +
+ Help regarding loose-objects +
\ No newline at end of file diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/help-prefetch.html b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/help-prefetch.html new file mode 100644 index 0000000000..1e18161577 --- /dev/null +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/help-prefetch.html @@ -0,0 +1,3 @@ +
+ Help regarding prefetch +
\ No newline at end of file diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly index 8b470e8e4e..68f281468f 100644 --- a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly @@ -10,11 +10,11 @@ - + From 7cb82bdbb645e2fad7f697389f5a9bb790561ca2 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 9 Jun 2022 01:34:17 +0530 Subject: [PATCH 004/146] added permissions --- .../git/maintenance/MaintenanceUI.java | 29 ++++++++++++++----- .../git/maintenance/MaintenanceUI/index.jelly | 2 +- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index 9642d2f08d..775a13c34f 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -3,12 +3,15 @@ import edu.umd.cs.findbugs.annotations.NonNull; import hudson.Extension; import hudson.model.ManagementLink; +import hudson.security.Permission; +import jenkins.model.Jenkins; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; import org.kohsuke.stapler.interceptor.RequirePOST; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.ArrayList; @@ -42,6 +45,10 @@ public String getDescription() { @RequirePOST @Restricted(NoExternalUse.class) public void doSave(StaplerRequest req, StaplerResponse res) throws IOException { + if (!Jenkins.get().hasPermission(Jenkins.ADMINISTER)) { + res.sendError(HttpServletResponse.SC_FORBIDDEN); + return; + } System.out.println("Saving"); res.sendRedirect(""); } @@ -49,6 +56,10 @@ public void doSave(StaplerRequest req, StaplerResponse res) throws IOException { @RequirePOST @Restricted(NoExternalUse.class) public void doExecute(StaplerRequest req, StaplerResponse res) throws IOException { + if (!Jenkins.get().hasPermission(Jenkins.ADMINISTER)) { + res.sendError(HttpServletResponse.SC_FORBIDDEN); + return; + } System.out.println("Executing..."); res.sendRedirect(""); } @@ -56,6 +67,10 @@ public void doExecute(StaplerRequest req, StaplerResponse res) throws IOExceptio @RequirePOST @Restricted(NoExternalUse.class) public void doTerminate(StaplerRequest req, StaplerResponse res) throws IOException { + if (!Jenkins.get().hasPermission(Jenkins.ADMINISTER)) { + res.sendError(HttpServletResponse.SC_FORBIDDEN); + return; + } System.out.println("Stopping..."); res.sendRedirect(""); } @@ -70,11 +85,11 @@ public ArrayList getMaintenanceTask(){ tasks.add(new TaskData("loose-objects","Click to view loose objects")); return tasks; } -// -// @NonNull -// @Override -// public Permission getRequiredPermission() { -// return Jenkins.ADMINISTER; -// } -// + + @NonNull + @Override + public Permission getRequiredPermission() { + return Jenkins.ADMINISTER; + } + } diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly index 68f281468f..034c5738ba 100644 --- a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly @@ -4,7 +4,7 @@
-

Maintenace Tasks

+

Maintenance Tasks

Enter cron syntax for periodic execution of maintenance tasks

From 97c34784568c79f7479ccdfd2a57417627a73c99 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 9 Jun 2022 02:54:58 +0530 Subject: [PATCH 005/146] Init maintenance config --- .../MaintenanceTaskConfiguration.java | 35 +++++++++++++++++++ .../git/maintenance/MaintenanceUI.java | 14 +++----- .../jenkins/plugins/git/maintenance/Task.java | 28 +++++++++++++++ .../plugins/git/maintenance/TaskData.java | 21 ----------- .../plugins/git/maintenance/TaskType.java | 5 +++ .../git/maintenance/MaintenanceUI/index.jelly | 2 +- .../MaintenanceTaskConfigurationTest.java | 35 +++++++++++++++++++ .../plugins/git/maintenance/TaskTest.java | 4 +++ 8 files changed, 113 insertions(+), 31 deletions(-) create mode 100644 src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java create mode 100644 src/main/java/jenkins/plugins/git/maintenance/Task.java delete mode 100644 src/main/java/jenkins/plugins/git/maintenance/TaskData.java create mode 100644 src/main/java/jenkins/plugins/git/maintenance/TaskType.java create mode 100644 src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java create mode 100644 src/test/java/jenkins/plugins/git/maintenance/TaskTest.java diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java new file mode 100644 index 0000000000..4be19d4efa --- /dev/null +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java @@ -0,0 +1,35 @@ +package jenkins.plugins.git.maintenance; + +import java.util.HashMap; +import java.util.Map; + +public class MaintenanceTaskConfiguration { + + Map maintenanceTasks; + + public MaintenanceTaskConfiguration(){ + configureMaintenanceTasks(); + } + private void configureMaintenanceTasks(){ + // check git version and based on git version, add the maintenance tasks to the list + maintenanceTasks = new HashMap<>(); + + maintenanceTasks.put(TaskType.COMMIT_GRAPH,new Task(TaskType.COMMIT_GRAPH,"Commit Graph msg")); + maintenanceTasks.put(TaskType.PREFETCH,new Task(TaskType.PREFETCH,"Prefetch msg")); + maintenanceTasks.put(TaskType.GC,new Task(TaskType.GC,"Gc msg")); + maintenanceTasks.put(TaskType.LOOSE_OBJECTS,new Task(TaskType.LOOSE_OBJECTS,"Loose Objects msg")); + maintenanceTasks.put(TaskType.INCREMENTAL_REPACK,new Task(TaskType.INCREMENTAL_REPACK,"Incremental Repack msg")); + } + + public Map getMaintenanceTasks(){ + return maintenanceTasks; + } + + public void setCronSyntax(TaskType taskType, String cronSyntax){ + Task updatedTask = maintenanceTasks.get(taskType); + updatedTask.setCronSyntax(cronSyntax); + maintenanceTasks.put(taskType,updatedTask); + } + + +} diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index 775a13c34f..0083e2d7ec 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -13,7 +13,7 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; -import java.util.ArrayList; +import java.util.Map; @Extension public class MaintenanceUI extends ManagementLink { @@ -75,15 +75,11 @@ public void doTerminate(StaplerRequest req, StaplerResponse res) throws IOExcept res.sendRedirect(""); } - public ArrayList getMaintenanceTask(){ + public Map getMaintenanceTask(){ // Can check if git version doesn't support a maintenance task and remove that maintenance task form the UI. - ArrayList tasks = new ArrayList(); - tasks.add(new TaskData("gc","Click to view gc")); - tasks.add(new TaskData("commit-graph","Click to view commit graph")); - tasks.add(new TaskData("incremental-repack","Click to view Incremental Repack")); - tasks.add(new TaskData("prefetch","Click to view prefetch")); - tasks.add(new TaskData("loose-objects","Click to view loose objects")); - return tasks; + + // Use a descriptor to remove hardcoded dependency + return new MaintenanceTaskConfiguration().getMaintenanceTasks(); } @NonNull diff --git a/src/main/java/jenkins/plugins/git/maintenance/Task.java b/src/main/java/jenkins/plugins/git/maintenance/Task.java new file mode 100644 index 0000000000..172d416fa8 --- /dev/null +++ b/src/main/java/jenkins/plugins/git/maintenance/Task.java @@ -0,0 +1,28 @@ +package jenkins.plugins.git.maintenance; + +public class Task { + + TaskType task; + String msg; + String cronSyntax; + boolean isConfigured; + + public Task(TaskType task, String msg){ + this.task = task; + this.msg = msg; + } + + public TaskType getTaskName(){ + return this.task; + } + + public String getTaskMessage(){ + return this.msg; + } + + public String getCronSyntax(){ return this.cronSyntax; } + + public void setCronSyntax(String cronSyntax){ + this.cronSyntax = cronSyntax; + } +} diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskData.java b/src/main/java/jenkins/plugins/git/maintenance/TaskData.java deleted file mode 100644 index 4d1a321478..0000000000 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskData.java +++ /dev/null @@ -1,21 +0,0 @@ -package jenkins.plugins.git.maintenance; - -public class TaskData { - - String task; - String msg; - - public TaskData(String task, String msg){ - this.task = task; - this.msg = msg; - } - - public String getTaskName(){ - return this.task; - } - - public String getTaskMessage(){ - return this.msg; - } - -} diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskType.java b/src/main/java/jenkins/plugins/git/maintenance/TaskType.java new file mode 100644 index 0000000000..bce0097cad --- /dev/null +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskType.java @@ -0,0 +1,5 @@ +package jenkins.plugins.git.maintenance; + +public enum TaskType { + GC,PREFETCH,COMMIT_GRAPH,LOOSE_OBJECTS,INCREMENTAL_REPACK +} diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly index 034c5738ba..eb9301a795 100644 --- a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly @@ -8,7 +8,7 @@

Enter cron syntax for periodic execution of maintenance tasks

- + diff --git a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java new file mode 100644 index 0000000000..54368a1f3f --- /dev/null +++ b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java @@ -0,0 +1,35 @@ +package jenkins.plugins.git.maintenance; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class MaintenanceTaskConfigurationTest { + + private final MaintenanceTaskConfiguration config = new MaintenanceTaskConfiguration(); + +// @Test +// public void configureMaintenanceTasks(){ +// config.configureMaintenanceTasks(); +// assertEquals(TaskType.GC,config.getMaintenanceTasks().get(TaskType.GC).task); +// assertEquals(TaskType.PREFETCH,config.getMaintenanceTasks().get(TaskType.PREFETCH).task); +// assertEquals(TaskType.INCREMENTAL_REPACK,config.getMaintenanceTasks().get(TaskType.INCREMENTAL_REPACK).task); +// assertEquals(TaskType.LOOSE_OBJECTS,config.getMaintenanceTasks().get(TaskType.LOOSE_OBJECTS).task); +// assertEquals(TaskType.COMMIT_GRAPH,config.getMaintenanceTasks().get(TaskType.COMMIT_GRAPH).task); +// } + + @Test + public void setCronSyntax(){ + String cronSyntax = "* * * 1 *"; + for(TaskType taskType : TaskType.values()){ + config.setCronSyntax(taskType,cronSyntax); + } + + for(TaskType taskType : TaskType.values()){ + Task maintenanceTask = config.getMaintenanceTasks().get(taskType); + assertEquals(cronSyntax,maintenanceTask.getCronSyntax()); + } + } + + +} diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskTest.java new file mode 100644 index 0000000000..b9ef46b05a --- /dev/null +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskTest.java @@ -0,0 +1,4 @@ +package jenkins.plugins.git.maintenance; + +public class TaskTest { +} From ad0222e753c39def6d52996ea1e12298211b5aff Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 9 Jun 2022 19:02:01 +0530 Subject: [PATCH 006/146] Conditional rendering button in UI --- .../MaintenanceTaskConfiguration.java | 17 ++++++++++++----- .../git/maintenance/MaintenanceUI.java | 15 +++++++++++++++ .../jenkins/plugins/git/maintenance/Task.java | 9 ++------- .../git/maintenance/MaintenanceUI/index.jelly | 19 +++++++++++-------- .../MaintenanceTaskConfigurationTest.java | 11 +++++++++++ 5 files changed, 51 insertions(+), 20 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java index 4be19d4efa..e37bf44af8 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java @@ -6,19 +6,23 @@ public class MaintenanceTaskConfiguration { Map maintenanceTasks; + boolean isGitMaintenanceRunning; public MaintenanceTaskConfiguration(){ + + // Load from Global configuration, if null, set default configuration. configureMaintenanceTasks(); + isGitMaintenanceRunning = false; } private void configureMaintenanceTasks(){ // check git version and based on git version, add the maintenance tasks to the list maintenanceTasks = new HashMap<>(); - maintenanceTasks.put(TaskType.COMMIT_GRAPH,new Task(TaskType.COMMIT_GRAPH,"Commit Graph msg")); - maintenanceTasks.put(TaskType.PREFETCH,new Task(TaskType.PREFETCH,"Prefetch msg")); - maintenanceTasks.put(TaskType.GC,new Task(TaskType.GC,"Gc msg")); - maintenanceTasks.put(TaskType.LOOSE_OBJECTS,new Task(TaskType.LOOSE_OBJECTS,"Loose Objects msg")); - maintenanceTasks.put(TaskType.INCREMENTAL_REPACK,new Task(TaskType.INCREMENTAL_REPACK,"Incremental Repack msg")); + maintenanceTasks.put(TaskType.COMMIT_GRAPH,new Task(TaskType.COMMIT_GRAPH)); + maintenanceTasks.put(TaskType.PREFETCH,new Task(TaskType.PREFETCH)); + maintenanceTasks.put(TaskType.GC,new Task(TaskType.GC)); + maintenanceTasks.put(TaskType.LOOSE_OBJECTS,new Task(TaskType.LOOSE_OBJECTS)); + maintenanceTasks.put(TaskType.INCREMENTAL_REPACK,new Task(TaskType.INCREMENTAL_REPACK)); } public Map getMaintenanceTasks(){ @@ -31,5 +35,8 @@ public void setCronSyntax(TaskType taskType, String cronSyntax){ maintenanceTasks.put(taskType,updatedTask); } + public boolean getIsGitMaintenanceTaskRunning(){ + return isGitMaintenanceRunning; + } } diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index 0083e2d7ec..d32416d2f1 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -49,6 +49,9 @@ public void doSave(StaplerRequest req, StaplerResponse res) throws IOException { res.sendError(HttpServletResponse.SC_FORBIDDEN); return; } + + // Responsible for saving the data internally inside jenkins... + System.out.println("Saving"); res.sendRedirect(""); } @@ -60,6 +63,11 @@ public void doExecute(StaplerRequest req, StaplerResponse res) throws IOExceptio res.sendError(HttpServletResponse.SC_FORBIDDEN); return; } + + // Change the status of execution to true... + + // Save the status of execution internally inside jenkins... + System.out.println("Executing..."); res.sendRedirect(""); } @@ -71,6 +79,9 @@ public void doTerminate(StaplerRequest req, StaplerResponse res) throws IOExcept res.sendError(HttpServletResponse.SC_FORBIDDEN); return; } + + // Change the status of execution to false and save the data internally... + System.out.println("Stopping..."); res.sendRedirect(""); } @@ -82,6 +93,10 @@ public Map getMaintenanceTask(){ return new MaintenanceTaskConfiguration().getMaintenanceTasks(); } + public boolean getIsMaintenanceTaskRunning(){ + return new MaintenanceTaskConfiguration().getIsGitMaintenanceTaskRunning(); + } + @NonNull @Override public Permission getRequiredPermission() { diff --git a/src/main/java/jenkins/plugins/git/maintenance/Task.java b/src/main/java/jenkins/plugins/git/maintenance/Task.java index 172d416fa8..47186cb0d9 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Task.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Task.java @@ -3,23 +3,18 @@ public class Task { TaskType task; - String msg; String cronSyntax; boolean isConfigured; - public Task(TaskType task, String msg){ + public Task(TaskType task){ + // Can add default cron syntax recommended by git documentation this.task = task; - this.msg = msg; } public TaskType getTaskName(){ return this.task; } - public String getTaskMessage(){ - return this.msg; - } - public String getCronSyntax(){ return this.cronSyntax; } public void setCronSyntax(String cronSyntax){ diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly index eb9301a795..126d1517b4 100644 --- a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly @@ -12,16 +12,19 @@
- +
- - - - - - - + + + + + + + + + +
diff --git a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java index 54368a1f3f..5efa8e2ba9 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java @@ -31,5 +31,16 @@ public void setCronSyntax(){ } } + @Test + public void setIsMaintenanceTaskRunning(){ + // When status is false. + boolean status = config.getIsGitMaintenanceTaskRunning(); + assertEquals(false,status); + + // When status is set to true + status = config.setIsGitMaintenanceTaskRunning(); + assertEquals(true,status); + + } } From 2130708d6add7fcd13aea00aee7251b7d776778f Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Fri, 10 Jun 2022 15:18:52 +0530 Subject: [PATCH 007/146] added taskNames and TaskTest --- .../jenkins/plugins/git/maintenance/Task.java | 6 ++- .../plugins/git/maintenance/TaskType.java | 15 +++++- .../git/maintenance/MaintenanceUI/index.jelly | 2 +- .../MaintenanceTaskConfigurationTest.java | 5 +- .../plugins/git/maintenance/TaskTest.java | 49 +++++++++++++++++++ 5 files changed, 71 insertions(+), 6 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/Task.java b/src/main/java/jenkins/plugins/git/maintenance/Task.java index 47186cb0d9..22ccaf3bb8 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Task.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Task.java @@ -11,10 +11,14 @@ public Task(TaskType task){ this.task = task; } - public TaskType getTaskName(){ + public TaskType getTaskType(){ return this.task; } + public String getTaskName(){ + return this.task.getTaskName(); + } + public String getCronSyntax(){ return this.cronSyntax; } public void setCronSyntax(String cronSyntax){ diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskType.java b/src/main/java/jenkins/plugins/git/maintenance/TaskType.java index bce0097cad..eb9cc07c2b 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskType.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskType.java @@ -1,5 +1,18 @@ package jenkins.plugins.git.maintenance; public enum TaskType { - GC,PREFETCH,COMMIT_GRAPH,LOOSE_OBJECTS,INCREMENTAL_REPACK + GC("Gc"), + PREFETCH("Prefetch"), + COMMIT_GRAPH("Commit Graph"), + LOOSE_OBJECTS("Loose Objects"), + INCREMENTAL_REPACK("Incremental Repack"); + + String taskName; + TaskType(String taskName){ + this.taskName = taskName; + } + + public String getTaskName(){ + return this.taskName; + } } diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly index 126d1517b4..d6c51620c2 100644 --- a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly @@ -8,7 +8,7 @@

Enter cron syntax for periodic execution of maintenance tasks

- + diff --git a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java index 5efa8e2ba9..5f1157fc00 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java @@ -38,9 +38,8 @@ public void setIsMaintenanceTaskRunning(){ assertEquals(false,status); // When status is set to true - status = config.setIsGitMaintenanceTaskRunning(); - assertEquals(true,status); - +// status = config.setIsGitMaintenanceTaskRunning(); +// assertEquals(true,status); } } diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskTest.java index b9ef46b05a..806b2fed94 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskTest.java @@ -1,4 +1,53 @@ package jenkins.plugins.git.maintenance; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +@RunWith(Parameterized.class) public class TaskTest { + + private Task task; + private TaskType taskType; + private String taskName; + + public TaskTest(Task task,TaskType taskType,String taskName){ + this.task = task; + this.taskType = taskType; + this.taskName = taskName; + } + + @Parameterized.Parameters(name="{0}") + public static Collection permuteTasks(){ + List tasks = new ArrayList<>(); + for(TaskType taskType : TaskType.values()){ + Object[] task = {new Task(taskType),taskType,taskType.getTaskName()}; + tasks.add(task); + } + + return tasks; + } + + @Test + public void getTaskType(){ + assertEquals(taskType,task.getTaskType()); + } + + @Test + public void getTaskName(){ + assertEquals(taskName,task.getTaskName()); + } + + @Test + public void checkCronSyntax(){ + String cronSyntax = "* * 1 * 1"; + task.setCronSyntax(cronSyntax); + assertEquals(cronSyntax,task.getCronSyntax()); + } } From d0befd7aaefa10f7c1e733e04e98f5f13866a0aa Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Fri, 10 Jun 2022 15:47:30 +0530 Subject: [PATCH 008/146] FormValidation init --- .../plugins/git/maintenance/MaintenanceUI.java | 18 ++++++++++++++++-- .../git/maintenance/MaintenanceUI/index.jelly | 4 ++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index d32416d2f1..e5eec002cf 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -4,13 +4,18 @@ import hudson.Extension; import hudson.model.ManagementLink; import hudson.security.Permission; +import hudson.util.FormValidation; import jenkins.model.Jenkins; +import net.sf.json.JSON; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; +import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; import org.kohsuke.stapler.interceptor.RequirePOST; +import org.kohsuke.stapler.verb.POST; +import javax.servlet.ServletException; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Map; @@ -44,14 +49,15 @@ public String getDescription() { @RequirePOST @Restricted(NoExternalUse.class) - public void doSave(StaplerRequest req, StaplerResponse res) throws IOException { + public void doSave(StaplerRequest req, StaplerResponse res) throws IOException, ServletException { if (!Jenkins.get().hasPermission(Jenkins.ADMINISTER)) { res.sendError(HttpServletResponse.SC_FORBIDDEN); return; } // Responsible for saving the data internally inside jenkins... - + JSON formData = req.getSubmittedForm(); + System.out.println(formData); System.out.println("Saving"); res.sendRedirect(""); } @@ -86,6 +92,14 @@ public void doTerminate(StaplerRequest req, StaplerResponse res) throws IOExcept res.sendRedirect(""); } + @POST + @Restricted(NoExternalUse.class) + public FormValidation doCheckCronSyntax(@QueryParameter String cronSyntax){ + Jenkins.get().checkPermission(Jenkins.ADMINISTER); + System.out.println(cronSyntax); + return FormValidation.ok(); + } + public Map getMaintenanceTask(){ // Can check if git version doesn't support a maintenance task and remove that maintenance task form the UI. diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly index d6c51620c2..d9073b855e 100644 --- a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly @@ -8,8 +8,8 @@

Enter cron syntax for periodic execution of maintenance tasks

- - + + From c9e298bad00d9ec7c4b83b49068f0ae3b96c3368 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Sat, 11 Jun 2022 04:10:35 +0530 Subject: [PATCH 009/146] Added Form Validation --- .../MaintenanceTaskConfiguration.java | 17 ++++++++++++++++ .../git/maintenance/MaintenanceUI.java | 20 +++++++++++++++---- .../git/maintenance/MaintenanceUI/index.jelly | 2 +- .../MaintenanceTaskConfigurationTest.java | 18 +++++++++++++++++ 4 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java index e37bf44af8..dabe7222fb 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java @@ -1,5 +1,8 @@ package jenkins.plugins.git.maintenance; +import antlr.ANTLRException; +import hudson.scheduler.CronTab; + import java.util.HashMap; import java.util.Map; @@ -39,4 +42,18 @@ public boolean getIsGitMaintenanceTaskRunning(){ return isGitMaintenanceRunning; } + public static String checkSanity(String cron) throws ANTLRException { + try { + CronTab cronTab = new CronTab(cron.trim()); + String msg = cronTab.checkSanity(); + if (msg != null) { + return msg; + } + return null; + }catch(ANTLRException e){ + if(cron.contains("**")) + throw new ANTLRException("You appear to be missing whitespace between * and *."); + throw new ANTLRException(String.format("Invalid input: \"%s\": %s", cron, e), e); + } + } } diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index e5eec002cf..db9637c670 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -1,5 +1,6 @@ package jenkins.plugins.git.maintenance; +import antlr.ANTLRException; import edu.umd.cs.findbugs.annotations.NonNull; import hudson.Extension; import hudson.model.ManagementLink; @@ -94,10 +95,21 @@ public void doTerminate(StaplerRequest req, StaplerResponse res) throws IOExcept @POST @Restricted(NoExternalUse.class) - public FormValidation doCheckCronSyntax(@QueryParameter String cronSyntax){ - Jenkins.get().checkPermission(Jenkins.ADMINISTER); - System.out.println(cronSyntax); - return FormValidation.ok(); + public FormValidation doCheckCronSyntax(@QueryParameter String cronSyntax) throws ANTLRException { + try { + Jenkins.get().checkPermission(Jenkins.ADMINISTER); + if (cronSyntax.isEmpty()) + return FormValidation.ok(); + + String msg = MaintenanceTaskConfiguration.checkSanity(cronSyntax); + + if (msg != null) { + return FormValidation.error(msg); + } + return FormValidation.ok(); + }catch(ANTLRException e){ + return FormValidation.error(e.getMessage()); + } } public Map getMaintenanceTask(){ diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly index d9073b855e..b1659185fc 100644 --- a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly @@ -9,7 +9,7 @@ - + diff --git a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java index 5f1157fc00..f442621142 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java @@ -1,5 +1,6 @@ package jenkins.plugins.git.maintenance; +import antlr.ANTLRException; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -42,4 +43,21 @@ public void setIsMaintenanceTaskRunning(){ // assertEquals(true,status); } + @Test + public void checkValidCronSyntax() throws ANTLRException { + + // Doesn't throw any error + MaintenanceTaskConfiguration.checkSanity("* * * * *"); + MaintenanceTaskConfiguration.checkSanity("1 * * * * "); + MaintenanceTaskConfiguration.checkSanity("H H(8-15)/2 * * 1-5"); + MaintenanceTaskConfiguration.checkSanity("H H 1,15 1-11 *"); + } + + @Test(expected = ANTLRException.class) + public void checkInvalidCronSyntax() throws ANTLRException{ + MaintenanceTaskConfiguration.checkSanity(""); + MaintenanceTaskConfiguration.checkSanity("*****"); + MaintenanceTaskConfiguration.checkSanity("a * * 1 *"); + } + } From fdc423f11f1fbd47254a2180370568dc17d44f4f Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Tue, 14 Jun 2022 23:00:05 +0530 Subject: [PATCH 010/146] Added checkbox to tasks in UI --- .../MaintenanceTaskConfiguration.java | 11 ++++++++--- .../plugins/git/maintenance/MaintenanceUI.java | 6 +++--- .../jenkins/plugins/git/maintenance/Task.java | 14 +++++++++++--- .../git/maintenance/MaintenanceUI/index.jelly | 14 ++++++++------ .../MaintenanceTaskConfigurationTest.java | 16 +++++++++++++++- .../plugins/git/maintenance/TaskTest.java | 7 +++++++ 6 files changed, 52 insertions(+), 16 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java index dabe7222fb..c11f9e30c8 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java @@ -8,8 +8,8 @@ public class MaintenanceTaskConfiguration { - Map maintenanceTasks; - boolean isGitMaintenanceRunning; + private Map maintenanceTasks; + private boolean isGitMaintenanceRunning; public MaintenanceTaskConfiguration(){ @@ -38,10 +38,15 @@ public void setCronSyntax(TaskType taskType, String cronSyntax){ maintenanceTasks.put(taskType,updatedTask); } - public boolean getIsGitMaintenanceTaskRunning(){ + public boolean getIsGitMaintenanceRunning(){ return isGitMaintenanceRunning; } + public void setIsTaskConfigured(TaskType taskType, boolean isConfigured){ + Task task = maintenanceTasks.get(taskType); + task.setIsTaskConfigured(isConfigured); + } + public static String checkSanity(String cron) throws ANTLRException { try { CronTab cronTab = new CronTab(cron.trim()); diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index db9637c670..4f78afb321 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -113,14 +113,14 @@ public FormValidation doCheckCronSyntax(@QueryParameter String cronSyntax) throw } public Map getMaintenanceTask(){ - // Can check if git version doesn't support a maintenance task and remove that maintenance task form the UI. + // Can check if git version doesn't support a maintenance task and remove that maintenance task from the UI. // Use a descriptor to remove hardcoded dependency return new MaintenanceTaskConfiguration().getMaintenanceTasks(); } - public boolean getIsMaintenanceTaskRunning(){ - return new MaintenanceTaskConfiguration().getIsGitMaintenanceTaskRunning(); + public boolean getIsGitMaintenanceRunning(){ + return new MaintenanceTaskConfiguration().getIsGitMaintenanceRunning(); } @NonNull diff --git a/src/main/java/jenkins/plugins/git/maintenance/Task.java b/src/main/java/jenkins/plugins/git/maintenance/Task.java index 22ccaf3bb8..645956ed5a 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Task.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Task.java @@ -2,9 +2,9 @@ public class Task { - TaskType task; - String cronSyntax; - boolean isConfigured; + private TaskType task; + private String cronSyntax; + private boolean isConfigured; public Task(TaskType task){ // Can add default cron syntax recommended by git documentation @@ -21,6 +21,14 @@ public String getTaskName(){ public String getCronSyntax(){ return this.cronSyntax; } + public void setIsTaskConfigured(boolean isConfigured){ + this.isConfigured = isConfigured; + } + + public boolean getIsTaskConfigured(){ + return this.isConfigured; + } + public void setCronSyntax(String cronSyntax){ this.cronSyntax = cronSyntax; } diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly index b1659185fc..416fd56d72 100644 --- a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly @@ -8,19 +8,21 @@

Enter cron syntax for periodic execution of maintenance tasks

- - - +
+ + + + +
- - + - + diff --git a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java index f442621142..6a9932b76f 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java @@ -32,10 +32,24 @@ public void setCronSyntax(){ } } + @Test + public void setIsMaintenanceTaskConfigured(){ + boolean isMaintenanceTaskConfigured = true; + + for(TaskType taskType : TaskType.values()){ + config.setIsTaskConfigured(taskType,isMaintenanceTaskConfigured); + } + + for(TaskType taskType : TaskType.values()){ + Task maintenanceTask = config.getMaintenanceTasks().get(taskType); + assertEquals(isMaintenanceTaskConfigured,maintenanceTask.getIsTaskConfigured()); + } + } + @Test public void setIsMaintenanceTaskRunning(){ // When status is false. - boolean status = config.getIsGitMaintenanceTaskRunning(); + boolean status = config.getIsGitMaintenanceRunning(); assertEquals(false,status); // When status is set to true diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskTest.java index 806b2fed94..de060a80b4 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskTest.java @@ -44,6 +44,13 @@ public void getTaskName(){ assertEquals(taskName,task.getTaskName()); } + @Test + public void setIsConfigured(){ + boolean isConfigured = true; + task.setIsTaskConfigured(isConfigured); + assertEquals(isConfigured,task.getIsTaskConfigured()); + } + @Test public void checkCronSyntax(){ String cronSyntax = "* * 1 * 1"; From e4141528fd28b082087af3058f06a13df35d661e Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Tue, 14 Jun 2022 23:30:03 -0600 Subject: [PATCH 011/146] Suppress a spotbugs warning --- .../plugins/git/maintenance/MaintenanceTaskConfiguration.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java index c11f9e30c8..6fa6224277 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java @@ -1,5 +1,7 @@ package jenkins.plugins.git.maintenance; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + import antlr.ANTLRException; import hudson.scheduler.CronTab; @@ -28,6 +30,8 @@ private void configureMaintenanceTasks(){ maintenanceTasks.put(TaskType.INCREMENTAL_REPACK,new Task(TaskType.INCREMENTAL_REPACK)); } + // FIXME: Don't ship with this suppressed - resolve the issue + @SuppressFBWarnings("EI_EXPOSE_REP") public Map getMaintenanceTasks(){ return maintenanceTasks; } From 95c2bd675ca232e0f5f866c1ba11afa124af0afa Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 16 Jun 2022 13:37:06 +0530 Subject: [PATCH 012/146] saving data in xml file --- .../MaintenanceTaskConfiguration.java | 7 +++++- .../git/maintenance/MaintenanceUI.java | 23 +++++++++++++++---- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java index 6fa6224277..b45d715fde 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java @@ -3,12 +3,15 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import antlr.ANTLRException; +import hudson.Extension; import hudson.scheduler.CronTab; +import jenkins.model.GlobalConfiguration; import java.util.HashMap; import java.util.Map; -public class MaintenanceTaskConfiguration { +@Extension +public class MaintenanceTaskConfiguration extends GlobalConfiguration { private Map maintenanceTasks; private boolean isGitMaintenanceRunning; @@ -46,6 +49,8 @@ public boolean getIsGitMaintenanceRunning(){ return isGitMaintenanceRunning; } + public void setIsGitMaintenanceRunning(){isGitMaintenanceRunning = !isGitMaintenanceRunning;} + public void setIsTaskConfigured(TaskType taskType, boolean isConfigured){ Task task = maintenanceTasks.get(taskType); task.setIsTaskConfigured(isConfigured); diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index 4f78afb321..ace38fc836 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -6,8 +6,9 @@ import hudson.model.ManagementLink; import hudson.security.Permission; import hudson.util.FormValidation; +import jenkins.model.GlobalConfiguration; import jenkins.model.Jenkins; -import net.sf.json.JSON; +import net.sf.json.JSONObject; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; import org.kohsuke.stapler.QueryParameter; @@ -56,9 +57,22 @@ public void doSave(StaplerRequest req, StaplerResponse res) throws IOException, return; } - // Responsible for saving the data internally inside jenkins... - JSON formData = req.getSubmittedForm(); - System.out.println(formData); + JSONObject formData = req.getSubmittedForm(); + MaintenanceTaskConfiguration config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); + + if(config != null) { + for (TaskType taskType : TaskType.values()) { + JSONObject maintenanceData = formData.getJSONObject(taskType.toString()); + String cronSyntax = maintenanceData.getString("cronSyntax"); + boolean isApplied = maintenanceData.getBoolean("isApplied"); + + // Need to perform form validation again to avoid incorrect save of data. + config.setCronSyntax(taskType, cronSyntax); + config.setIsTaskConfigured(taskType, isApplied); + } + config.save(); + } + System.out.println("Saving"); res.sendRedirect(""); } @@ -115,7 +129,6 @@ public FormValidation doCheckCronSyntax(@QueryParameter String cronSyntax) throw public Map getMaintenanceTask(){ // Can check if git version doesn't support a maintenance task and remove that maintenance task from the UI. - // Use a descriptor to remove hardcoded dependency return new MaintenanceTaskConfiguration().getMaintenanceTasks(); } From 7c9f3bfa01d61166f984e04ba5a8a88ade4c68fa Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 16 Jun 2022 14:18:46 +0530 Subject: [PATCH 013/146] Fixed EI_EXPOSE_REP spotbug error --- .../MaintenanceTaskConfiguration.java | 15 ++++++++------ .../git/maintenance/MaintenanceUI.java | 17 ++++++++++++---- .../git/maintenance/MaintenanceUI/index.jelly | 6 +++--- .../MaintenanceTaskConfigurationTest.java | 20 +++++++++++++++---- 4 files changed, 41 insertions(+), 17 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java index b45d715fde..b0f38647d8 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java @@ -1,13 +1,14 @@ package jenkins.plugins.git.maintenance; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; - import antlr.ANTLRException; +import com.google.common.collect.ImmutableList; import hudson.Extension; import hudson.scheduler.CronTab; import jenkins.model.GlobalConfiguration; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; @Extension @@ -33,10 +34,12 @@ private void configureMaintenanceTasks(){ maintenanceTasks.put(TaskType.INCREMENTAL_REPACK,new Task(TaskType.INCREMENTAL_REPACK)); } - // FIXME: Don't ship with this suppressed - resolve the issue - @SuppressFBWarnings("EI_EXPOSE_REP") - public Map getMaintenanceTasks(){ - return maintenanceTasks; + public List getMaintenanceTasks(){ + List maintenanceTasks = new ArrayList<>(); + for(Map.Entry entry : this.maintenanceTasks.entrySet()){ + maintenanceTasks.add(entry.getValue()); + } + return ImmutableList.copyOf(maintenanceTasks); } public void setCronSyntax(TaskType taskType, String cronSyntax){ diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index ace38fc836..178a31ac4b 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -20,7 +20,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletResponse; import java.io.IOException; -import java.util.Map; +import java.util.List; @Extension public class MaintenanceUI extends ManagementLink { @@ -126,14 +126,23 @@ public FormValidation doCheckCronSyntax(@QueryParameter String cronSyntax) throw } } - public Map getMaintenanceTask(){ + public List getMaintenanceTasks(){ // Can check if git version doesn't support a maintenance task and remove that maintenance task from the UI. + MaintenanceTaskConfiguration config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); + if(config != null) + return config.getMaintenanceTasks(); - return new MaintenanceTaskConfiguration().getMaintenanceTasks(); + // need to throw error; + return null; } public boolean getIsGitMaintenanceRunning(){ - return new MaintenanceTaskConfiguration().getIsGitMaintenanceRunning(); + MaintenanceTaskConfiguration config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); + if(config != null) + return config.getIsGitMaintenanceRunning(); + + // need to throw error; + return false; } @NonNull diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly index 416fd56d72..4b91c2b917 100644 --- a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly @@ -7,9 +7,9 @@

Maintenance Tasks

Enter cron syntax for periodic execution of maintenance tasks

- -
- + +
+ diff --git a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java index 6a9932b76f..4b8a6a970c 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java @@ -3,6 +3,8 @@ import antlr.ANTLRException; import org.junit.Test; +import java.util.List; + import static org.junit.Assert.assertEquals; public class MaintenanceTaskConfigurationTest { @@ -27,8 +29,13 @@ public void setCronSyntax(){ } for(TaskType taskType : TaskType.values()){ - Task maintenanceTask = config.getMaintenanceTasks().get(taskType); - assertEquals(cronSyntax,maintenanceTask.getCronSyntax()); + List maintenanceTasks = config.getMaintenanceTasks(); + for(Task task : maintenanceTasks){ + if(task.getTaskType().equals(taskType)){ + assertEquals(cronSyntax,task.getCronSyntax()); + break; + } + } } } @@ -41,8 +48,13 @@ public void setIsMaintenanceTaskConfigured(){ } for(TaskType taskType : TaskType.values()){ - Task maintenanceTask = config.getMaintenanceTasks().get(taskType); - assertEquals(isMaintenanceTaskConfigured,maintenanceTask.getIsTaskConfigured()); + List maintenanceTasks = config.getMaintenanceTasks(); + for(Task task : maintenanceTasks){ + if(task.getTaskType().equals(taskType)){ + assertEquals(isMaintenanceTaskConfigured,task.getIsTaskConfigured()); + break; + } + } } } From cd36d1ec38dc422953ec11b840b57ca7ed2a1ad9 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 16 Jun 2022 15:49:31 +0530 Subject: [PATCH 014/146] Loading maintenance data from xml files --- .../MaintenanceTaskConfiguration.java | 11 +++++---- .../git/maintenance/MaintenanceUI.java | 24 +++++-------------- .../git/maintenance/MaintenanceUI/index.jelly | 20 +++++++--------- 3 files changed, 22 insertions(+), 33 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java index b0f38647d8..03e5ddebcc 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java @@ -19,12 +19,15 @@ public class MaintenanceTaskConfiguration extends GlobalConfiguration { public MaintenanceTaskConfiguration(){ - // Load from Global configuration, if null, set default configuration. - configureMaintenanceTasks(); - isGitMaintenanceRunning = false; + load(); + if(maintenanceTasks == null) { + configureMaintenanceTasks(); + isGitMaintenanceRunning = false; + } } private void configureMaintenanceTasks(){ - // check git version and based on git version, add the maintenance tasks to the list + // check git version and based on git version, add the maintenance tasks to the list + // Can add default cron syntax for maintenance tasks. maintenanceTasks = new HashMap<>(); maintenanceTasks.put(TaskType.COMMIT_GRAPH,new Task(TaskType.COMMIT_GRAPH)); diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index 178a31ac4b..cd937ce69e 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -79,31 +79,19 @@ public void doSave(StaplerRequest req, StaplerResponse res) throws IOException, @RequirePOST @Restricted(NoExternalUse.class) - public void doExecute(StaplerRequest req, StaplerResponse res) throws IOException { + public void doToggleExecutionState(StaplerRequest req, StaplerResponse res) throws IOException { if (!Jenkins.get().hasPermission(Jenkins.ADMINISTER)) { res.sendError(HttpServletResponse.SC_FORBIDDEN); return; } - // Change the status of execution to true... - - // Save the status of execution internally inside jenkins... - - System.out.println("Executing..."); - res.sendRedirect(""); - } - - @RequirePOST - @Restricted(NoExternalUse.class) - public void doTerminate(StaplerRequest req, StaplerResponse res) throws IOException { - if (!Jenkins.get().hasPermission(Jenkins.ADMINISTER)) { - res.sendError(HttpServletResponse.SC_FORBIDDEN); - return; + MaintenanceTaskConfiguration config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); + if(config != null) { + config.setIsGitMaintenanceRunning(); + config.save(); } - // Change the status of execution to false and save the data internally... - - System.out.println("Stopping..."); + System.out.println("Executing..."); res.sendRedirect(""); } diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly index 4b91c2b917..4756bd4c2e 100644 --- a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly @@ -10,23 +10,21 @@
- - + +
- - - + + + + + + + - - - - - -
From 12e4926e80f35b6cb3b5ab59ebd56309b258e7d3 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Fri, 17 Jun 2022 03:43:54 +0530 Subject: [PATCH 015/146] Added jenkinsRule for failing tests --- .../java/jenkins/plugins/git/maintenance/CronScheduler.java | 4 ++++ .../git/maintenance/MaintenanceTaskConfigurationTest.java | 4 ++++ 2 files changed, 8 insertions(+) create mode 100644 src/main/java/jenkins/plugins/git/maintenance/CronScheduler.java diff --git a/src/main/java/jenkins/plugins/git/maintenance/CronScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/CronScheduler.java new file mode 100644 index 0000000000..669cc8ccc7 --- /dev/null +++ b/src/main/java/jenkins/plugins/git/maintenance/CronScheduler.java @@ -0,0 +1,4 @@ +package jenkins.plugins.git.maintenance; + +public class CronScheduler { +} diff --git a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java index 4b8a6a970c..760e8a95dc 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java @@ -1,7 +1,9 @@ package jenkins.plugins.git.maintenance; import antlr.ANTLRException; +import org.junit.ClassRule; import org.junit.Test; +import org.jvnet.hudson.test.JenkinsRule; import java.util.List; @@ -9,6 +11,8 @@ public class MaintenanceTaskConfigurationTest { + @ClassRule + public static JenkinsRule j = new JenkinsRule(); private final MaintenanceTaskConfiguration config = new MaintenanceTaskConfiguration(); // @Test From a75d13da20de69c0ad3bc8ca4e68eb7ac5685348 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Fri, 17 Jun 2022 17:41:23 +0530 Subject: [PATCH 016/146] init maintenance scheduling --- .../jenkins/plugins/git/maintenance/Cron.java | 36 ++++++++++++++++++ .../{CronScheduler.java => TaskExecutor.java} | 2 +- .../git/maintenance/TaskScheduler.java | 37 +++++++++++++++++++ .../git/maintenance/TaskSchedulerTest.java | 13 +++++++ 4 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 src/main/java/jenkins/plugins/git/maintenance/Cron.java rename src/main/java/jenkins/plugins/git/maintenance/{CronScheduler.java => TaskExecutor.java} (60%) create mode 100644 src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java create mode 100644 src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java diff --git a/src/main/java/jenkins/plugins/git/maintenance/Cron.java b/src/main/java/jenkins/plugins/git/maintenance/Cron.java new file mode 100644 index 0000000000..50c9b443db --- /dev/null +++ b/src/main/java/jenkins/plugins/git/maintenance/Cron.java @@ -0,0 +1,36 @@ +package jenkins.plugins.git.maintenance; + +import hudson.Extension; +import hudson.model.PeriodicWork; + +import java.util.Calendar; +import java.util.concurrent.TimeUnit; + +@Extension +public class Cron extends PeriodicWork { + + TaskScheduler taskScheduler; + + @Override + public long getInitialDelay(){ + return MIN - (Calendar.getInstance().get(Calendar.SECOND) * 1000); + } + + @Override + public long getRecurrencePeriod() { + return TimeUnit.MINUTES.toMillis(1); + } + + @Override + protected void doRun() throws Exception { + scheduleMaintenanceTask(); + } + + private void scheduleMaintenanceTask(){ + if(taskScheduler == null){ + taskScheduler = new TaskScheduler(); + } + + taskScheduler.scheduleTasks(); + } +} diff --git a/src/main/java/jenkins/plugins/git/maintenance/CronScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java similarity index 60% rename from src/main/java/jenkins/plugins/git/maintenance/CronScheduler.java rename to src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index 669cc8ccc7..bd3aebcc5f 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/CronScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -1,4 +1,4 @@ package jenkins.plugins.git.maintenance; -public class CronScheduler { +public class TaskExecutor { } diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java new file mode 100644 index 0000000000..a26ab24094 --- /dev/null +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -0,0 +1,37 @@ +package jenkins.plugins.git.maintenance; + +import jenkins.model.GlobalConfiguration; + +import java.util.Calendar; +import java.util.Collections; +import java.util.GregorianCalendar; +import java.util.LinkedList; +import java.util.List; + +public class TaskScheduler { + + MaintenanceTaskConfiguration config; + Calendar cal; + List maintenanceQueue; + public TaskScheduler(){ + this.config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); + this.cal = new GregorianCalendar(); + this.maintenanceQueue = Collections.synchronizedList(new LinkedList()); + } + + public void scheduleTasks(){ + assert config != null; + + if(!config.getIsGitMaintenanceRunning()) + return; + + List configuredTasks = config.getMaintenanceTasks(); + + boolean isSchedulable = false; +// for(Task task : configuredTasks){ +// isSchedulable = task.isTaskSchedulable(cal); +// +// +// } + } +} diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java new file mode 100644 index 0000000000..19228f7329 --- /dev/null +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java @@ -0,0 +1,13 @@ +package jenkins.plugins.git.maintenance; + +import org.junit.Test; + +public class TaskSchedulerTest { + + private final TaskScheduler taskScheduler = new TaskScheduler(); + + @Test + public void scheduleMaintenanceTask(){ +// taskScheduler.scheduleTasks(); + } +} From a987fa3bef192c529eae166aaf6b3d82fe5c83f2 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Fri, 17 Jun 2022 18:42:15 +0530 Subject: [PATCH 017/146] added task scheduling --- .../MaintenanceTaskConfiguration.java | 2 +- .../git/maintenance/MaintenanceUI.java | 10 ++++--- .../jenkins/plugins/git/maintenance/Task.java | 20 +++++++++++++- .../git/maintenance/TaskScheduler.java | 23 +++++++++++----- .../MaintenanceTaskConfigurationTest.java | 2 +- .../git/maintenance/TaskSchedulerTest.java | 8 +++++- .../plugins/git/maintenance/TaskTest.java | 27 ++++++++++++++++--- 7 files changed, 75 insertions(+), 17 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java index 03e5ddebcc..0d862dd3be 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java @@ -45,7 +45,7 @@ public List getMaintenanceTasks(){ return ImmutableList.copyOf(maintenanceTasks); } - public void setCronSyntax(TaskType taskType, String cronSyntax){ + public void setCronSyntax(TaskType taskType, String cronSyntax) throws ANTLRException { Task updatedTask = maintenanceTasks.get(taskType); updatedTask.setCronSyntax(cronSyntax); maintenanceTasks.put(taskType,updatedTask); diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index cd937ce69e..179ff8f9be 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -60,7 +60,8 @@ public void doSave(StaplerRequest req, StaplerResponse res) throws IOException, JSONObject formData = req.getSubmittedForm(); MaintenanceTaskConfiguration config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); - if(config != null) { + try{ + assert config != null; for (TaskType taskType : TaskType.values()) { JSONObject maintenanceData = formData.getJSONObject(taskType.toString()); String cronSyntax = maintenanceData.getString("cronSyntax"); @@ -71,10 +72,13 @@ public void doSave(StaplerRequest req, StaplerResponse res) throws IOException, config.setIsTaskConfigured(taskType, isApplied); } config.save(); + System.out.println("Saving"); + res.sendRedirect(""); + }catch (ANTLRException e){ + // Throw antlr exception and display error on UI. + System.out.println("Invalid cron syntax, will display error on screen"); } - System.out.println("Saving"); - res.sendRedirect(""); } @RequirePOST diff --git a/src/main/java/jenkins/plugins/git/maintenance/Task.java b/src/main/java/jenkins/plugins/git/maintenance/Task.java index 645956ed5a..90bca01a36 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Task.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Task.java @@ -1,11 +1,20 @@ package jenkins.plugins.git.maintenance; +import antlr.ANTLRException; +import hudson.scheduler.CronTab; +import hudson.scheduler.CronTabList; + +import java.util.Calendar; +import java.util.Collections; + public class Task { private TaskType task; private String cronSyntax; private boolean isConfigured; + private CronTabList cronTabList; + public Task(TaskType task){ // Can add default cron syntax recommended by git documentation this.task = task; @@ -29,7 +38,16 @@ public boolean getIsTaskConfigured(){ return this.isConfigured; } - public void setCronSyntax(String cronSyntax){ + public void setCronSyntax(String cronSyntax) throws ANTLRException { this.cronSyntax = cronSyntax; + setCronTabList(cronSyntax); + } + + private void setCronTabList(String cronSyntax) throws ANTLRException { + cronTabList = new CronTabList(Collections.singletonList(new CronTab(cronSyntax))); + } + + public boolean checkIsTaskExecutable(Calendar cal){ + return cronTabList.check(cal); } } diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index a26ab24094..f01ca3dd71 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -27,11 +27,22 @@ public void scheduleTasks(){ List configuredTasks = config.getMaintenanceTasks(); - boolean isSchedulable = false; -// for(Task task : configuredTasks){ -// isSchedulable = task.isTaskSchedulable(cal); -// -// -// } + boolean isTaskExecutable = false; + for(Task task : configuredTasks){ + if(!task.getIsTaskConfigured() || checkIsTaskInQueue(task)) + continue; + + isTaskExecutable = task.checkIsTaskExecutable(cal); + if(isTaskExecutable){ + maintenanceQueue.add(task); + } + } + + // Create a new thread and execute the tasks present in the queue + System.out.println(maintenanceQueue); + } + + private boolean checkIsTaskInQueue(Task task){ + return maintenanceQueue.stream().anyMatch(queuedTask -> queuedTask.getTaskType().equals(task.getTaskType())); } } diff --git a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java index 760e8a95dc..c611ff0f5d 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java @@ -26,7 +26,7 @@ public class MaintenanceTaskConfigurationTest { // } @Test - public void setCronSyntax(){ + public void setCronSyntax() throws ANTLRException { String cronSyntax = "* * * 1 *"; for(TaskType taskType : TaskType.values()){ config.setCronSyntax(taskType,cronSyntax); diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java index 19228f7329..beb2df3014 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java @@ -2,12 +2,18 @@ import org.junit.Test; +import static org.junit.Assert.assertTrue; + public class TaskSchedulerTest { private final TaskScheduler taskScheduler = new TaskScheduler(); @Test public void scheduleMaintenanceTask(){ -// taskScheduler.scheduleTasks(); + boolean isFalse = false; + + // Need to discuss how to test this method + taskScheduler.scheduleTasks(); + assertTrue(isFalse); } } diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskTest.java index de060a80b4..1606a0d6f7 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskTest.java @@ -1,21 +1,26 @@ package jenkins.plugins.git.maintenance; +import antlr.ANTLRException; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import java.util.ArrayList; +import java.util.Calendar; import java.util.Collection; +import java.util.GregorianCalendar; import java.util.List; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; @RunWith(Parameterized.class) public class TaskTest { - private Task task; - private TaskType taskType; - private String taskName; + private final Task task; + private final TaskType taskType; + private final String taskName; public TaskTest(Task task,TaskType taskType,String taskName){ this.task = task; @@ -52,9 +57,23 @@ public void setIsConfigured(){ } @Test - public void checkCronSyntax(){ + public void checkCronSyntax() throws ANTLRException { String cronSyntax = "* * 1 * 1"; task.setCronSyntax(cronSyntax); assertEquals(cronSyntax,task.getCronSyntax()); } + + @Test + public void isTaskExecutable() throws ANTLRException { + Calendar cal = new GregorianCalendar(); + String cronSyntax = "* * * * *"; + task.setCronSyntax(cronSyntax); + boolean isTaskExecutable = task.checkIsTaskExecutable(cal); + assertTrue(isTaskExecutable); + + cronSyntax = "H * * * *"; + task.setCronSyntax(cronSyntax); + isTaskExecutable = task.checkIsTaskExecutable(cal); + assertFalse(isTaskExecutable); + } } From ded1f1be4bd877d90133f953583cda3eca6cd344 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Sat, 18 Jun 2022 01:54:54 +0530 Subject: [PATCH 018/146] init maintenance task executor --- .../plugins/git/maintenance/TaskExecutor.java | 15 ++++++++++++++- .../plugins/git/maintenance/TaskScheduler.java | 12 ++++++++++-- .../plugins/git/maintenance/TaskExecutorTest.java | 4 ++++ 3 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index bd3aebcc5f..90c4298a48 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -1,4 +1,17 @@ package jenkins.plugins.git.maintenance; -public class TaskExecutor { +import java.util.List; + +public class TaskExecutor implements Runnable { + + List maintenanceQueue; + public TaskExecutor(List maintenanceQueue){ + this.maintenanceQueue = maintenanceQueue; + } + @Override + public void run() { + // Need a way to iterate through all the caches present on Jenkins controller. + // Need to get the Git Client from the Git-Client-Plugin. + // Execute Maintenance Tasks in this class. + } } diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index f01ca3dd71..72b5dc4197 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -13,6 +13,7 @@ public class TaskScheduler { MaintenanceTaskConfiguration config; Calendar cal; List maintenanceQueue; + Thread taskExecutor; public TaskScheduler(){ this.config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); this.cal = new GregorianCalendar(); @@ -27,7 +28,7 @@ public void scheduleTasks(){ List configuredTasks = config.getMaintenanceTasks(); - boolean isTaskExecutable = false; + boolean isTaskExecutable; for(Task task : configuredTasks){ if(!task.getIsTaskConfigured() || checkIsTaskInQueue(task)) continue; @@ -38,7 +39,14 @@ public void scheduleTasks(){ } } - // Create a new thread and execute the tasks present in the queue + // Create a new thread and execute the tasks present in the queue; + if(!maintenanceQueue.isEmpty() && (taskExecutor == null || !taskExecutor.isAlive())) { + System.out.println("Entered this statement"); + taskExecutor = new Thread(new TaskExecutor(maintenanceQueue), "maintenance-task-executor"); + taskExecutor.start(); + } + + System.out.println(taskExecutor.isAlive() + " Status of execution after"); System.out.println(maintenanceQueue); } diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java new file mode 100644 index 0000000000..8b5988d6ce --- /dev/null +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java @@ -0,0 +1,4 @@ +package jenkins.plugins.git.maintenance; + +public class TaskExecutorTest { +} From 634c48600514196e66d9e7894a5623183be703d4 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Sat, 18 Jun 2022 21:41:07 +0530 Subject: [PATCH 019/146] added permissions and git version in UI --- .../jenkins/plugins/git/maintenance/MaintenanceUI.java | 4 ++++ .../plugins/git/maintenance/MaintenanceUI/index.jelly | 7 ++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index 179ff8f9be..67ee7376b6 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -137,6 +137,10 @@ public boolean getIsGitMaintenanceRunning(){ return false; } + public String getGitVersion(){ + return "2.36.1"; + } + @NonNull @Override public Permission getRequiredPermission() { diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly index 4756bd4c2e..aac9c1e841 100644 --- a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly @@ -1,23 +1,24 @@ - +

Maintenance Tasks

+

Git Version: ${it.getGitVersion()} (HardCoded Value)

Enter cron syntax for periodic execution of maintenance tasks

- +
- + From ad7e6035d5a3fbf543ae6c5bb2f7528b4cccbe55 Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Sun, 19 Jun 2022 05:36:01 -0600 Subject: [PATCH 020/146] Use JenkinsRule in TaskSchedulerTest Move the constructor call for the tested object so that it happens after the creation of the JenkinsRule and its matching Jenkins instance. --- .../plugins/git/maintenance/TaskSchedulerTest.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java index beb2df3014..894c8a54c7 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java @@ -3,17 +3,23 @@ import org.junit.Test; import static org.junit.Assert.assertTrue; +import org.junit.Rule; +import org.jvnet.hudson.test.JenkinsRule; public class TaskSchedulerTest { - private final TaskScheduler taskScheduler = new TaskScheduler(); + @Rule + public JenkinsRule j = new JenkinsRule(); + + private TaskScheduler taskScheduler; @Test - public void scheduleMaintenanceTask(){ + public void scheduleMaintenanceTask() { + taskScheduler = new TaskScheduler(); boolean isFalse = false; // Need to discuss how to test this method taskScheduler.scheduleTasks(); - assertTrue(isFalse); + assertTrue(!isFalse); } } From a88800c993af0c0efcc9c1103566a8ea84b9b30a Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Sun, 19 Jun 2022 07:38:56 -0600 Subject: [PATCH 021/146] Make checkIsTaskInQueue testable (pacakge protected) Include a simple test or two --- .../git/maintenance/TaskScheduler.java | 3 ++- .../git/maintenance/TaskSchedulerTest.java | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index 72b5dc4197..d6e1c8afe3 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -50,7 +50,8 @@ public void scheduleTasks(){ System.out.println(maintenanceQueue); } - private boolean checkIsTaskInQueue(Task task){ + /* Package protected for use by tests */ + boolean checkIsTaskInQueue(Task task){ return maintenanceQueue.stream().anyMatch(queuedTask -> queuedTask.getTaskType().equals(task.getTaskType())); } } diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java index 894c8a54c7..0c31cfcf11 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java @@ -1,8 +1,10 @@ package jenkins.plugins.git.maintenance; +import static org.junit.Assert.assertFalse; import org.junit.Test; import static org.junit.Assert.assertTrue; +import org.junit.Before; import org.junit.Rule; import org.jvnet.hudson.test.JenkinsRule; @@ -13,13 +15,28 @@ public class TaskSchedulerTest { private TaskScheduler taskScheduler; + @Before + public void setUp() throws Exception { + taskScheduler = new TaskScheduler(); + } + @Test public void scheduleMaintenanceTask() { - taskScheduler = new TaskScheduler(); boolean isFalse = false; // Need to discuss how to test this method taskScheduler.scheduleTasks(); assertTrue(!isFalse); } + + @Test + public void testScheduleTasks() { + taskScheduler.scheduleTasks(); + } + + @Test + public void testCheckIsTaskInQueue() { + Task task = new Task(TaskType.PREFETCH); + assertFalse(taskScheduler.checkIsTaskInQueue(task)); + } } From 0562df79ccd188495f6d352615a9960613cb0fca Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Sun, 19 Jun 2022 08:34:05 -0600 Subject: [PATCH 022/146] Add a few task tests Throw more general Exception from a test rather than ANTLRException to reduce future test maintenance. Add comment reminder that cron syntax would be a good candidate to parameterize the test in addition to the existing task type parameterization. --- .../plugins/git/maintenance/TaskTest.java | 104 ++++++++++++++---- 1 file changed, 84 insertions(+), 20 deletions(-) diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskTest.java index 1606a0d6f7..988354e06a 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskTest.java @@ -1,6 +1,5 @@ package jenkins.plugins.git.maintenance; -import antlr.ANTLRException; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -11,9 +10,10 @@ import java.util.GregorianCalendar; import java.util.List; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; @RunWith(Parameterized.class) public class TaskTest { @@ -22,17 +22,17 @@ public class TaskTest { private final TaskType taskType; private final String taskName; - public TaskTest(Task task,TaskType taskType,String taskName){ + public TaskTest(Task task, TaskType taskType, String taskName) { this.task = task; this.taskType = taskType; this.taskName = taskName; } - @Parameterized.Parameters(name="{0}") - public static Collection permuteTasks(){ + @Parameterized.Parameters(name = "{0}") + public static Collection permuteTasks() { List tasks = new ArrayList<>(); - for(TaskType taskType : TaskType.values()){ - Object[] task = {new Task(taskType),taskType,taskType.getTaskName()}; + for (TaskType taskType : TaskType.values()) { + Object[] task = {new Task(taskType), taskType, taskType.getTaskName()}; tasks.add(task); } @@ -40,40 +40,104 @@ public static Collection permuteTasks(){ } @Test - public void getTaskType(){ - assertEquals(taskType,task.getTaskType()); + public void getTaskType() { + assertThat(task.getTaskType(), is(taskType)); } @Test - public void getTaskName(){ - assertEquals(taskName,task.getTaskName()); + public void getTaskName() { + assertThat(task.getTaskName(), is(taskName)); } @Test - public void setIsConfigured(){ - boolean isConfigured = true; - task.setIsTaskConfigured(isConfigured); - assertEquals(isConfigured,task.getIsTaskConfigured()); + public void setIsConfigured() { + task.setIsTaskConfigured(true); + assertTrue(task.getIsTaskConfigured()); } @Test - public void checkCronSyntax() throws ANTLRException { + public void checkCronSyntax() throws Exception { String cronSyntax = "* * 1 * 1"; task.setCronSyntax(cronSyntax); - assertEquals(cronSyntax,task.getCronSyntax()); + assertThat(task.getCronSyntax(), is(cronSyntax)); } @Test - public void isTaskExecutable() throws ANTLRException { + public void isTaskExecutable() throws Exception { Calendar cal = new GregorianCalendar(); String cronSyntax = "* * * * *"; task.setCronSyntax(cronSyntax); boolean isTaskExecutable = task.checkIsTaskExecutable(cal); assertTrue(isTaskExecutable); + } - cronSyntax = "H * * * *"; + @Test + public void isTaskExecutableWithHSyntax() throws Exception { + Calendar cal = new GregorianCalendar(); + String cronSyntax = "H * * * *"; task.setCronSyntax(cronSyntax); - isTaskExecutable = task.checkIsTaskExecutable(cal); + boolean isTaskExecutable = task.checkIsTaskExecutable(cal); assertFalse(isTaskExecutable); } + + @Test + public void testGetTaskType() { + assertThat(task.getTaskType(), is(taskType)); + } + + @Test + public void testGetTaskName() { + assertThat(task.getTaskName(), is(taskName)); + } + + @Test + public void testGetCronSyntax() throws Exception { + String cronSyntax = "* * 1 * 1"; + task.setCronSyntax(cronSyntax); + assertThat(task.getCronSyntax(), is(cronSyntax)); + } + + @Test + public void testSetIsTaskConfigured() { + task.setIsTaskConfigured(true); + assertTrue(task.getIsTaskConfigured()); + } + + @Test + public void testGetIsTaskConfigured() { + task.setIsTaskConfigured(true); + assertTrue(task.getIsTaskConfigured()); + } + + @Test + public void testGetIsTaskConfiguredFalse() { + task.setIsTaskConfigured(false); + assertFalse(task.getIsTaskConfigured()); + } + + // Syntax not yet supported by this class + // Should parameterize test for cron syntax as well + // @Test + public void testSetCronSyntaxDaily() throws Exception { + Calendar cal = new GregorianCalendar(); + task.setCronSyntax("@daily"); + assertTrue(task.checkIsTaskExecutable(cal)); + } + + // Should parameterize test for cron syntax as well + @Test + public void testCheckIsTaskExecutable() throws Exception { + Calendar cal = new GregorianCalendar(); + String cronSyntax = "* * * * *"; + task.setCronSyntax(cronSyntax); + assertTrue(task.checkIsTaskExecutable(cal)); + } + + // Should parameterize test for cron syntax as well + @Test + public void testCheckIsTaskExecutableWithHSyntax() throws Exception { + Calendar cal = new GregorianCalendar(); + task.setCronSyntax("H * * * *"); + assertFalse(task.checkIsTaskExecutable(cal)); + } } From 2e0d8db16bf0ce8de8f26bfe28646a0dfc56e1dd Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Sun, 19 Jun 2022 14:06:19 -0600 Subject: [PATCH 023/146] Fix spotbugs warnings --- .../jenkins/plugins/git/maintenance/TaskExecutor.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index 90c4298a48..4aaa4a66d8 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -1,13 +1,21 @@ package jenkins.plugins.git.maintenance; +import java.util.ArrayList; import java.util.List; public class TaskExecutor implements Runnable { List maintenanceQueue; + public TaskExecutor(List maintenanceQueue){ - this.maintenanceQueue = maintenanceQueue; + /* Defensive copy avoids risk of caller modifying the queue after object creation */ + this.maintenanceQueue = new ArrayList<>(maintenanceQueue); + } + + public int queueLength() { + return maintenanceQueue.size(); } + @Override public void run() { // Need a way to iterate through all the caches present on Jenkins controller. From a0cbc634f3ddeafdefa33bd185bc1bfacd4c59dc Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Mon, 20 Jun 2022 03:27:51 +0530 Subject: [PATCH 024/146] Added tests to TaskScheduler --- .../git/maintenance/TaskScheduler.java | 37 +++++---- .../git/maintenance/TaskSchedulerTest.java | 75 +++++++++++++++---- 2 files changed, 84 insertions(+), 28 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index d6e1c8afe3..fa594d2e2c 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -23,11 +23,31 @@ public TaskScheduler(){ public void scheduleTasks(){ assert config != null; - if(!config.getIsGitMaintenanceRunning()) + if(!isGitMaintenanceTaskRunning(config)) return; List configuredTasks = config.getMaintenanceTasks(); + addTasksToQueue(configuredTasks); + createTaskExecutorThread(); + System.out.println(taskExecutor.isAlive() + " Status of execution after"); + System.out.println(maintenanceQueue); + } + + boolean checkIsTaskInQueue(Task task){ + return maintenanceQueue.stream().anyMatch(queuedTask -> queuedTask.getTaskType().equals(task.getTaskType())); + } + + void createTaskExecutorThread(){ + // Create a new thread and execute the tasks present in the queue; + if(!maintenanceQueue.isEmpty() && (taskExecutor == null || !taskExecutor.isAlive())) { + System.out.println("Entered this statement"); + taskExecutor = new Thread(new TaskExecutor(maintenanceQueue), "maintenance-task-executor"); + taskExecutor.start(); + } + } + + void addTasksToQueue(List configuredTasks){ boolean isTaskExecutable; for(Task task : configuredTasks){ if(!task.getIsTaskConfigured() || checkIsTaskInQueue(task)) @@ -38,20 +58,9 @@ public void scheduleTasks(){ maintenanceQueue.add(task); } } - - // Create a new thread and execute the tasks present in the queue; - if(!maintenanceQueue.isEmpty() && (taskExecutor == null || !taskExecutor.isAlive())) { - System.out.println("Entered this statement"); - taskExecutor = new Thread(new TaskExecutor(maintenanceQueue), "maintenance-task-executor"); - taskExecutor.start(); - } - - System.out.println(taskExecutor.isAlive() + " Status of execution after"); - System.out.println(maintenanceQueue); } - /* Package protected for use by tests */ - boolean checkIsTaskInQueue(Task task){ - return maintenanceQueue.stream().anyMatch(queuedTask -> queuedTask.getTaskType().equals(task.getTaskType())); + boolean isGitMaintenanceTaskRunning(MaintenanceTaskConfiguration config){ + return config.getIsGitMaintenanceRunning(); } } diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java index 0c31cfcf11..460fe6ac25 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java @@ -1,42 +1,89 @@ package jenkins.plugins.git.maintenance; -import static org.junit.Assert.assertFalse; -import org.junit.Test; - -import static org.junit.Assert.assertTrue; import org.junit.Before; import org.junit.Rule; +import org.junit.Test; import org.jvnet.hudson.test.JenkinsRule; +import java.util.List; +import java.util.stream.Collectors; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + public class TaskSchedulerTest { @Rule public JenkinsRule j = new JenkinsRule(); private TaskScheduler taskScheduler; + private MaintenanceTaskConfiguration config; @Before public void setUp() throws Exception { taskScheduler = new TaskScheduler(); + config = new MaintenanceTaskConfiguration(); + } @Test - public void scheduleMaintenanceTask() { - boolean isFalse = false; - - // Need to discuss how to test this method + public void testScheduleTasks() { taskScheduler.scheduleTasks(); - assertTrue(!isFalse); } @Test - public void testScheduleTasks() { - taskScheduler.scheduleTasks(); + public void testCheckIsTaskInQueue() throws Exception { + config.setCronSyntax(TaskType.PREFETCH,"* * * * *"); + config.setIsTaskConfigured(TaskType.PREFETCH,true); + + config.setCronSyntax(TaskType.COMMIT_GRAPH,"* * * * *"); + config.setIsTaskConfigured(TaskType.COMMIT_GRAPH,true); + + List maintenanceTasks = config.getMaintenanceTasks(); + taskScheduler.addTasksToQueue(maintenanceTasks); + + List configuredTask = config.getMaintenanceTasks().stream().filter(Task::getIsTaskConfigured).collect(Collectors.toList()); + + configuredTask.forEach(task -> assertTrue(taskScheduler.checkIsTaskInQueue(task))); + } + + @Test + public void testAddTasksToQueue() throws Exception { + // Adding Maintenance tasks configuration; + config.setCronSyntax(TaskType.PREFETCH,"* * * * *"); + config.setIsTaskConfigured(TaskType.PREFETCH,true); + config.setCronSyntax(TaskType.LOOSE_OBJECTS,"* * * * *"); + config.setIsTaskConfigured(TaskType.LOOSE_OBJECTS,true); + + config.setCronSyntax(TaskType.GC,"5 1 1 1 1"); + config.setIsTaskConfigured(TaskType.GC,true); + config.setCronSyntax(TaskType.COMMIT_GRAPH,"H * * * *"); + List maintenanceTasks = config.getMaintenanceTasks(); + + int length = 2; + + taskScheduler.addTasksToQueue(maintenanceTasks); + assertThat(taskScheduler.maintenanceQueue.size(),is(length)); } @Test - public void testCheckIsTaskInQueue() { - Task task = new Task(TaskType.PREFETCH); - assertFalse(taskScheduler.checkIsTaskInQueue(task)); + public void testIsGitMaintenanceTaskRunning(){ + // Setting value to true + config.setIsGitMaintenanceRunning(); + boolean isGitMaintenanceTaskRunning = taskScheduler.isGitMaintenanceTaskRunning(config); + assertTrue(isGitMaintenanceTaskRunning); + + // set value to false + config.setIsGitMaintenanceRunning(); + isGitMaintenanceTaskRunning = taskScheduler.isGitMaintenanceTaskRunning(config); + assertFalse(isGitMaintenanceTaskRunning); + } + + + // Need to think about this logic for testing. Issue while creating the thread + public void testCreateExecutorThread(){ + } } From ff425c6a9e068ca855876a0c5a920aa4a6e2552e Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Mon, 20 Jun 2022 04:12:58 +0530 Subject: [PATCH 025/146] updated logic in taskExecutor --- .../plugins/git/maintenance/TaskExecutor.java | 15 ++++----------- .../plugins/git/maintenance/TaskScheduler.java | 6 +++--- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index 4aaa4a66d8..27799db699 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -1,19 +1,11 @@ package jenkins.plugins.git.maintenance; -import java.util.ArrayList; -import java.util.List; - public class TaskExecutor implements Runnable { - List maintenanceQueue; - - public TaskExecutor(List maintenanceQueue){ - /* Defensive copy avoids risk of caller modifying the queue after object creation */ - this.maintenanceQueue = new ArrayList<>(maintenanceQueue); - } + Task maintenanceTask; - public int queueLength() { - return maintenanceQueue.size(); + public TaskExecutor(Task maintenanceTask){ + this.maintenanceTask = maintenanceTask; } @Override @@ -21,5 +13,6 @@ public void run() { // Need a way to iterate through all the caches present on Jenkins controller. // Need to get the Git Client from the Git-Client-Plugin. // Execute Maintenance Tasks in this class. + } } diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index fa594d2e2c..71985a0da5 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -28,10 +28,10 @@ public void scheduleTasks(){ List configuredTasks = config.getMaintenanceTasks(); addTasksToQueue(configuredTasks); - createTaskExecutorThread(); + // Option of Using the same thread for executing more maintenance task, or create a new thread the next minute and execute the maintenance task. + createTaskExecutorThread(); System.out.println(taskExecutor.isAlive() + " Status of execution after"); - System.out.println(maintenanceQueue); } boolean checkIsTaskInQueue(Task task){ @@ -42,7 +42,7 @@ void createTaskExecutorThread(){ // Create a new thread and execute the tasks present in the queue; if(!maintenanceQueue.isEmpty() && (taskExecutor == null || !taskExecutor.isAlive())) { System.out.println("Entered this statement"); - taskExecutor = new Thread(new TaskExecutor(maintenanceQueue), "maintenance-task-executor"); + taskExecutor = new Thread(new TaskExecutor(maintenanceQueue.remove(0)), "maintenance-task-executor"); taskExecutor.start(); } } From ff5b49db0dafd0540c2fec748fc75385adb56a77 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Mon, 20 Jun 2022 11:46:28 +0530 Subject: [PATCH 026/146] getAllCaches on controller added getCachesDir on controller added --- .../plugins/git/AbstractGitSCMSource.java | 50 +++++++++++-------- .../git/maintenance/GitMaintenanceSCM.java | 21 ++++++++ .../plugins/git/maintenance/TaskExecutor.java | 8 +++ .../git/maintenance/TaskScheduler.java | 4 +- 4 files changed, 61 insertions(+), 22 deletions(-) create mode 100644 src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java diff --git a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java index aa08eb197c..07d009ea0e 100644 --- a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java +++ b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java @@ -55,27 +55,6 @@ import hudson.plugins.git.util.GitUtils; import hudson.scm.SCM; import hudson.security.ACL; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.TreeSet; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.regex.Pattern; import jenkins.model.Jenkins; import jenkins.plugins.git.traits.GitBrowserSCMSourceTrait; import jenkins.plugins.git.traits.GitSCMExtensionTrait; @@ -122,6 +101,28 @@ import org.kohsuke.accmod.restrictions.NoExternalUse; import org.kohsuke.stapler.export.Exported; +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Pattern; + /** * Base class for {@link SCMSource} implementations that produce {@link GitSCM} implementations. * @@ -1243,6 +1244,13 @@ protected String getCacheEntry() { return getCacheEntry(getRemote()); } + protected static File[] getCachesDir(){ + Jenkins jenkins = Jenkins.getInstanceOrNull(); + if(jenkins == null) + return null; + return new File(jenkins.getRootDir(),"caches").listFiles(); + } + protected static File getCacheDir(String cacheEntry) { return getCacheDir(cacheEntry, true); } diff --git a/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java b/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java new file mode 100644 index 0000000000..102a07e2fb --- /dev/null +++ b/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java @@ -0,0 +1,21 @@ +package jenkins.plugins.git.maintenance; + +import jenkins.plugins.git.AbstractGitSCMSource; + +import java.io.File; + +public class GitMaintenanceSCM extends AbstractGitSCMSource { + @Override + public String getCredentialsId() { + return null; + } + + @Override + public String getRemote() { + return null; + } + + public static File[] getCachesDirectory(){ + return getCachesDir(); + } +} diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index 27799db699..19e7b2d481 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -1,11 +1,15 @@ package jenkins.plugins.git.maintenance; +import java.io.File; + public class TaskExecutor implements Runnable { Task maintenanceTask; + File[] cachesDir; public TaskExecutor(Task maintenanceTask){ this.maintenanceTask = maintenanceTask; + cachesDir = getCachesDir(); } @Override @@ -15,4 +19,8 @@ public void run() { // Execute Maintenance Tasks in this class. } + + File[] getCachesDir(){ + return GitMaintenanceSCM.getCachesDirectory(); + } } diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index 71985a0da5..9b53623e82 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -42,7 +42,9 @@ void createTaskExecutorThread(){ // Create a new thread and execute the tasks present in the queue; if(!maintenanceQueue.isEmpty() && (taskExecutor == null || !taskExecutor.isAlive())) { System.out.println("Entered this statement"); - taskExecutor = new Thread(new TaskExecutor(maintenanceQueue.remove(0)), "maintenance-task-executor"); + Task currentTask = maintenanceQueue.remove(0); + // Need to guard the currentTask to prevent state change. + taskExecutor = new Thread(new TaskExecutor(currentTask), "maintenance-task-executor"); taskExecutor.start(); } } From 078dfb41714dc716a92d4741742345a3065a1816 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Mon, 20 Jun 2022 12:57:05 +0530 Subject: [PATCH 027/146] added gitClient initialization --- .../plugins/git/maintenance/TaskExecutor.java | 44 ++++++++++++++++++- .../git/maintenance/TaskScheduler.java | 1 - 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index 19e7b2d481..2c457e8a7b 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -1,6 +1,14 @@ package jenkins.plugins.git.maintenance; +import hudson.FilePath; +import hudson.model.TaskListener; +import hudson.plugins.git.GitTool; +import hudson.plugins.git.util.GitUtils; +import org.jenkinsci.plugins.gitclient.Git; +import org.jenkinsci.plugins.gitclient.GitClient; + import java.io.File; +import java.io.IOException; public class TaskExecutor implements Runnable { @@ -14,13 +22,45 @@ public TaskExecutor(Task maintenanceTask){ @Override public void run() { - // Need a way to iterate through all the caches present on Jenkins controller. - // Need to get the Git Client from the Git-Client-Plugin. // Execute Maintenance Tasks in this class. + // TODO + // Need to get the Git Client from the Git-Client-Plugin. + // Need to add locks while running maintenance tasks on caches and remove locks after the maintenance tasks. + + GitClient gitClient; + for(File file : cachesDir){ + try { + gitClient = getGitClient(file); + + // Need to add git maintenance command in git client plugin + + } catch (IOException e) { + + throw new RuntimeException(e); + } catch (InterruptedException e) { + + throw new RuntimeException(e); + } + } + } File[] getCachesDir(){ return GitMaintenanceSCM.getCachesDirectory(); } + + GitClient getGitClient(File file) throws IOException, InterruptedException { + // What exactly is default tool here? + TaskListener listener = TaskListener.NULL; + GitTool gitTool = GitUtils.resolveGitTool("Default", listener); + if(gitTool == null) + return null; + + String gitExe = gitTool.getGitExe(); + FilePath workspace = new FilePath(file); + Git git = Git.with(listener,null).in(workspace).using(gitExe); + + return git.getClient(); + } } diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index 9b53623e82..5ec1c9c7e5 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -41,7 +41,6 @@ boolean checkIsTaskInQueue(Task task){ void createTaskExecutorThread(){ // Create a new thread and execute the tasks present in the queue; if(!maintenanceQueue.isEmpty() && (taskExecutor == null || !taskExecutor.isAlive())) { - System.out.println("Entered this statement"); Task currentTask = maintenanceQueue.remove(0); // Need to guard the currentTask to prevent state change. taskExecutor = new Thread(new TaskExecutor(currentTask), "maintenance-task-executor"); From a23f3953b7e60027f9b09ecaa5fd65aa924f8aa0 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Mon, 20 Jun 2022 12:57:05 +0530 Subject: [PATCH 028/146] added gitClient initialization --- .../jenkins/plugins/git/maintenance/TaskScheduler.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index 5ec1c9c7e5..f7d6827c6d 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -1,5 +1,6 @@ package jenkins.plugins.git.maintenance; +import com.google.gson.Gson; import jenkins.model.GlobalConfiguration; import java.util.Calendar; @@ -42,8 +43,10 @@ void createTaskExecutorThread(){ // Create a new thread and execute the tasks present in the queue; if(!maintenanceQueue.isEmpty() && (taskExecutor == null || !taskExecutor.isAlive())) { Task currentTask = maintenanceQueue.remove(0); - // Need to guard the currentTask to prevent state change. - taskExecutor = new Thread(new TaskExecutor(currentTask), "maintenance-task-executor"); + Gson gson = new Gson(); + // To avoid mutatbility + Task copyCurrentTask = gson.fromJson(gson.toJson(currentTask),Task.class); + taskExecutor = new Thread(new TaskExecutor(copyCurrentTask), "maintenance-task-executor"); taskExecutor.start(); } } From b7c3f1e32a0167cc99300539a64c6897611ffea2 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Mon, 20 Jun 2022 19:50:35 +0530 Subject: [PATCH 029/146] attempt to fix spotbug issue --- .../java/jenkins/plugins/git/maintenance/Cron.java | 3 ++- .../java/jenkins/plugins/git/maintenance/Task.java | 7 +++++++ .../jenkins/plugins/git/maintenance/TaskExecutor.java | 6 ++++-- .../plugins/git/maintenance/TaskScheduler.java | 11 ++++------- .../plugins/git/maintenance/TaskSchedulerTest.java | 3 ++- 5 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/Cron.java b/src/main/java/jenkins/plugins/git/maintenance/Cron.java index 50c9b443db..b309e81126 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Cron.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Cron.java @@ -1,5 +1,6 @@ package jenkins.plugins.git.maintenance; +import antlr.ANTLRException; import hudson.Extension; import hudson.model.PeriodicWork; @@ -26,7 +27,7 @@ protected void doRun() throws Exception { scheduleMaintenanceTask(); } - private void scheduleMaintenanceTask(){ + private void scheduleMaintenanceTask() throws ANTLRException { if(taskScheduler == null){ taskScheduler = new TaskScheduler(); } diff --git a/src/main/java/jenkins/plugins/git/maintenance/Task.java b/src/main/java/jenkins/plugins/git/maintenance/Task.java index 90bca01a36..d591e26ce2 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Task.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Task.java @@ -20,6 +20,13 @@ public Task(TaskType task){ this.task = task; } + public Task(Task copyTask) throws ANTLRException { + // Used for copying the task; + this(copyTask.getTaskType()); + setCronSyntax(copyTask.getCronSyntax()); + setIsTaskConfigured(copyTask.getIsTaskConfigured()); + } + public TaskType getTaskType(){ return this.task; } diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index 2c457e8a7b..34970128c1 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -1,5 +1,6 @@ package jenkins.plugins.git.maintenance; +import antlr.ANTLRException; import hudson.FilePath; import hudson.model.TaskListener; import hudson.plugins.git.GitTool; @@ -15,8 +16,8 @@ public class TaskExecutor implements Runnable { Task maintenanceTask; File[] cachesDir; - public TaskExecutor(Task maintenanceTask){ - this.maintenanceTask = maintenanceTask; + public TaskExecutor(Task maintenanceTask) throws ANTLRException { + this.maintenanceTask = new Task(maintenanceTask); cachesDir = getCachesDir(); } @@ -32,6 +33,7 @@ public void run() { for(File file : cachesDir){ try { gitClient = getGitClient(file); + TaskType taskType = maintenanceTask.getTaskType(); // Need to add git maintenance command in git client plugin diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index f7d6827c6d..154a01306d 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -1,6 +1,6 @@ package jenkins.plugins.git.maintenance; -import com.google.gson.Gson; +import antlr.ANTLRException; import jenkins.model.GlobalConfiguration; import java.util.Calendar; @@ -21,7 +21,7 @@ public TaskScheduler(){ this.maintenanceQueue = Collections.synchronizedList(new LinkedList()); } - public void scheduleTasks(){ + public void scheduleTasks() throws ANTLRException { assert config != null; if(!isGitMaintenanceTaskRunning(config)) @@ -39,14 +39,11 @@ boolean checkIsTaskInQueue(Task task){ return maintenanceQueue.stream().anyMatch(queuedTask -> queuedTask.getTaskType().equals(task.getTaskType())); } - void createTaskExecutorThread(){ + void createTaskExecutorThread() throws ANTLRException { // Create a new thread and execute the tasks present in the queue; if(!maintenanceQueue.isEmpty() && (taskExecutor == null || !taskExecutor.isAlive())) { Task currentTask = maintenanceQueue.remove(0); - Gson gson = new Gson(); - // To avoid mutatbility - Task copyCurrentTask = gson.fromJson(gson.toJson(currentTask),Task.class); - taskExecutor = new Thread(new TaskExecutor(copyCurrentTask), "maintenance-task-executor"); + taskExecutor = new Thread(new TaskExecutor(currentTask), "maintenance-task-executor"); taskExecutor.start(); } } diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java index 460fe6ac25..53e61f0e3b 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java @@ -1,5 +1,6 @@ package jenkins.plugins.git.maintenance; +import antlr.ANTLRException; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -29,7 +30,7 @@ public void setUp() throws Exception { } @Test - public void testScheduleTasks() { + public void testScheduleTasks() throws ANTLRException { taskScheduler.scheduleTasks(); } From 9a6eadbad1e1484f21fcfc2fbd41126aa683735d Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Tue, 21 Jun 2022 21:24:31 -0600 Subject: [PATCH 030/146] Depend on incremental git client build --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index 9b8385c063..39eac9e14f 100644 --- a/pom.xml +++ b/pom.xml @@ -102,6 +102,7 @@ org.jenkins-ci.plugins git-client + 3.11.1-20220622.031254-1 org.jenkins-ci.plugins From a311417530d96e8141dc04d9cbb63ff03680ca61 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Wed, 22 Jun 2022 09:02:36 +0530 Subject: [PATCH 031/146] updated verion of git-client plugin --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 39eac9e14f..8092c5adb6 100644 --- a/pom.xml +++ b/pom.xml @@ -102,7 +102,7 @@ org.jenkins-ci.plugins git-client - 3.11.1-20220622.031254-1 + 3.11.1-rc3079.3cb_12b_8fe875 org.jenkins-ci.plugins From a432fad1d1331c02e16cdc93739ca93c33cf03db Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Tue, 21 Jun 2022 21:38:42 -0600 Subject: [PATCH 032/146] Revert "updated verion of git-client plugin" Incremental build not available because the pull request branch did not include the full contents of the master branch. New build coming soon. This reverts commit da5c7e333af07b58ca3fd39020a9608534ed03da. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8092c5adb6..39eac9e14f 100644 --- a/pom.xml +++ b/pom.xml @@ -102,7 +102,7 @@ org.jenkins-ci.plugins git-client - 3.11.1-rc3079.3cb_12b_8fe875 + 3.11.1-20220622.031254-1 org.jenkins-ci.plugins From 69384152a743e5c6f861a2c4c777bdeec56ea89a Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 23 Jun 2022 13:59:33 +0530 Subject: [PATCH 033/146] logic to execute maintenance tasks --- pom.xml | 2 +- .../plugins/git/maintenance/TaskExecutor.java | 23 ++++++++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 39eac9e14f..0f67cc0c2c 100644 --- a/pom.xml +++ b/pom.xml @@ -102,7 +102,7 @@ org.jenkins-ci.plugins git-client - 3.11.1-20220622.031254-1 + 3.11.1-rc3079.e3ca_994f5da_a_ org.jenkins-ci.plugins diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index 34970128c1..ea3571ce4d 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -26,16 +26,15 @@ public void run() { // Execute Maintenance Tasks in this class. // TODO - // Need to get the Git Client from the Git-Client-Plugin. // Need to add locks while running maintenance tasks on caches and remove locks after the maintenance tasks. GitClient gitClient; for(File file : cachesDir){ try { + System.out.println("entered the thread"); gitClient = getGitClient(file); TaskType taskType = maintenanceTask.getTaskType(); - - // Need to add git maintenance command in git client plugin + executeMaintenanceTask(gitClient,taskType); } catch (IOException e) { @@ -48,6 +47,24 @@ public void run() { } + void executeMaintenanceTask(GitClient gitClient,TaskType taskType){ + + if(taskType.equals(TaskType.GC)){ + gitClient.maintenance("gc"); + }else if(taskType.equals(TaskType.COMMIT_GRAPH)){ + gitClient.maintenance("commit-graph"); + }else if(taskType.equals(TaskType.PREFETCH)){ + gitClient.maintenance("prefetch"); + }else if(taskType.equals(TaskType.INCREMENTAL_REPACK)){ + gitClient.maintenance("incremental-repack"); + }else if(taskType.equals(TaskType.LOOSE_OBJECTS)){ + gitClient.maintenance("loose-objects"); + }else{ + // Error + } + + } + File[] getCachesDir(){ return GitMaintenanceSCM.getCachesDirectory(); } From 10b92ba573003039816615a47c379f0e9afc0b24 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 23 Jun 2022 14:53:25 +0530 Subject: [PATCH 034/146] Retrieve cacheEntries --- .../plugins/git/AbstractGitSCMSource.java | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java index 07d009ea0e..f609693c51 100644 --- a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java +++ b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java @@ -105,6 +105,7 @@ import java.io.IOException; import java.net.URISyntaxException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -168,6 +169,19 @@ public abstract class AbstractGitSCMSource extends SCMSource { private static final Logger LOGGER = Logger.getLogger(AbstractGitSCMSource.class.getName()); + static Set cacheEntries; + + static { + Jenkins jenkins = Jenkins.getInstanceOrNull(); + if(jenkins != null){ + File[] caches = new File(jenkins.getRootDir(),"caches").listFiles(); + for(File cache : caches){ + String cacheEntry = cache.getName(); + cacheEntries.add(cacheEntry); + } + } + } + public AbstractGitSCMSource() { } @@ -1244,11 +1258,8 @@ protected String getCacheEntry() { return getCacheEntry(getRemote()); } - protected static File[] getCachesDir(){ - Jenkins jenkins = Jenkins.getInstanceOrNull(); - if(jenkins == null) - return null; - return new File(jenkins.getRootDir(),"caches").listFiles(); + protected static Set getCacheEntries(){ + return cacheEntries; } protected static File getCacheDir(String cacheEntry) { @@ -1265,6 +1276,7 @@ protected static File getCacheDir(String cacheEntry, boolean createDirectory) { if (!cacheDir.isDirectory()) { if (createDirectory) { boolean ok = cacheDir.mkdirs(); + cacheEntries.add(cacheEntry); if (!ok) { LOGGER.log(Level.WARNING, "Failed mkdirs of {0}", cacheDir); } From f5c8b998d2d4b30f71dce39f2e233ccc021a06de Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 23 Jun 2022 16:05:22 +0530 Subject: [PATCH 035/146] Init execution of maintenance tasks using locks --- .../plugins/git/AbstractGitSCMSource.java | 3 +- .../git/maintenance/GitMaintenanceSCM.java | 40 ++++++++++++++++++- .../plugins/git/maintenance/TaskExecutor.java | 38 +++++++++++------- 3 files changed, 63 insertions(+), 18 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java index f609693c51..97bf938911 100644 --- a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java +++ b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java @@ -105,7 +105,6 @@ import java.io.IOException; import java.net.URISyntaxException; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -169,7 +168,7 @@ public abstract class AbstractGitSCMSource extends SCMSource { private static final Logger LOGGER = Logger.getLogger(AbstractGitSCMSource.class.getName()); - static Set cacheEntries; + static Set cacheEntries = new HashSet<>(); static { Jenkins jenkins = Jenkins.getInstanceOrNull(); diff --git a/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java b/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java index 102a07e2fb..c7b7debcef 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java +++ b/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java @@ -1,10 +1,33 @@ package jenkins.plugins.git.maintenance; +import jenkins.model.Jenkins; import jenkins.plugins.git.AbstractGitSCMSource; import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.locks.Lock; public class GitMaintenanceSCM extends AbstractGitSCMSource { + + static class Cache { + + File cache; + Lock lock; + Cache(File cache, Lock lock){ + this.cache = cache; + this.lock = lock; + } + + public File getCacheFile(){ + return cache; + } + + public Lock getLock(){ + return lock; + } + + } @Override public String getCredentialsId() { return null; @@ -15,7 +38,20 @@ public String getRemote() { return null; } - public static File[] getCachesDirectory(){ - return getCachesDir(); + public static List getCaches(){ + Jenkins jenkins = Jenkins.getInstanceOrNull(); + + if(jenkins == null){ + // Throw error; + } + + List caches = new ArrayList<>(); + for (String cacheEntry : getCacheEntries()) { + File cacheDir = getCacheDir(cacheEntry); + Lock cacheLock = getCacheLock(cacheEntry); + caches.add(new Cache(cacheDir,cacheLock)); + } + + return caches; } } diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index ea3571ce4d..7ed79d6816 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -10,44 +10,54 @@ import java.io.File; import java.io.IOException; +import java.util.List; +import java.util.concurrent.locks.Lock; public class TaskExecutor implements Runnable { Task maintenanceTask; - File[] cachesDir; + List caches; public TaskExecutor(Task maintenanceTask) throws ANTLRException { this.maintenanceTask = new Task(maintenanceTask); - cachesDir = getCachesDir(); + caches = getCaches(); } @Override public void run() { + + System.out.println("Entered the Thread"); // Execute Maintenance Tasks in this class. // TODO - // Need to add locks while running maintenance tasks on caches and remove locks after the maintenance tasks. GitClient gitClient; - for(File file : cachesDir){ + for(GitMaintenanceSCM.Cache cache : caches){ + + // For now adding lock to all kinds of maintenance tasks. Need to study on which task needs a lock and which doesn't. + Lock lock = cache.getLock(); try { - System.out.println("entered the thread"); - gitClient = getGitClient(file); + File cacheFile = cache.getCacheFile(); + System.out.println("Executing maintenance task for " + cacheFile.getName()); + gitClient = getGitClient(cacheFile); TaskType taskType = maintenanceTask.getTaskType(); - executeMaintenanceTask(gitClient,taskType); - } catch (IOException e) { + lock.lock(); + System.out.println("Locked the cache"); - throw new RuntimeException(e); - } catch (InterruptedException e) { + executeMaintenanceTask(gitClient,taskType); - throw new RuntimeException(e); + } catch (IOException | InterruptedException e) { + System.out.println("Need to handle error"); + }finally { + lock.unlock(); + System.out.println("Unlocked the cache"); } } } - void executeMaintenanceTask(GitClient gitClient,TaskType taskType){ + void executeMaintenanceTask(GitClient gitClient,TaskType taskType) throws InterruptedException{ if(taskType.equals(TaskType.GC)){ gitClient.maintenance("gc"); @@ -65,8 +75,8 @@ void executeMaintenanceTask(GitClient gitClient,TaskType taskType){ } - File[] getCachesDir(){ - return GitMaintenanceSCM.getCachesDirectory(); + List getCaches(){ + return GitMaintenanceSCM.getCaches(); } GitClient getGitClient(File file) throws IOException, InterruptedException { From 52d4c07118bd4c5210ddec5152441d56e2be8334 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 23 Jun 2022 22:45:17 +0530 Subject: [PATCH 036/146] init tests for maintenance task execution --- .../git/maintenance/GitMaintenanceSCM.java | 11 ++++- .../maintenance/GitMaintenanceSCMTest.java | 31 ++++++++++++++ .../git/maintenance/TaskExecutorTest.java | 41 +++++++++++++++++++ 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java diff --git a/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java b/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java index c7b7debcef..f56f17dc82 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java +++ b/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java @@ -10,6 +10,11 @@ public class GitMaintenanceSCM extends AbstractGitSCMSource { + String remote; + protected GitMaintenanceSCM(String remote){ + this.remote = remote; + } + static class Cache { File cache; @@ -35,7 +40,7 @@ public String getCredentialsId() { @Override public String getRemote() { - return null; + return remote; } public static List getCaches(){ @@ -54,4 +59,8 @@ public static List getCaches(){ return caches; } + + static File getCacheDirectory(String cacheEntry,boolean createDirectory){ + return getCacheDir(cacheEntry,createDirectory); + } } diff --git a/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java b/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java new file mode 100644 index 0000000000..b06c2b8198 --- /dev/null +++ b/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java @@ -0,0 +1,31 @@ +package jenkins.plugins.git.maintenance; + +import jenkins.plugins.git.GitSampleRepoRule; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.jvnet.hudson.test.JenkinsRule; + +import java.util.List; + +public class GitMaintenanceSCMTest { + + @Rule + public GitSampleRepoRule sampleRepo = new GitSampleRepoRule(); + + @Rule + public JenkinsRule j = new JenkinsRule(); + + @Before + public void setUp() throws Exception { + // Need to create git caches on Jenkins controller. + + } + + @Test + public void testGetCaches(){ + List caches = GitMaintenanceSCM.getCaches(); + // check the given caches is same as the caches present on jenkins controller. + + } +} diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java index 8b5988d6ce..bdfd7aca44 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java @@ -1,4 +1,45 @@ package jenkins.plugins.git.maintenance; +import antlr.ANTLRException; +import jenkins.model.Jenkins; +import org.junit.Before; +import org.junit.Test; +import org.junit.runners.Parameterized; + +import java.io.File; +import java.lang.reflect.Executable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + public class TaskExecutorTest { + + TaskExecutor taskExecutor; + + public TaskExecutorTest(TaskExecutor taskExecutor){ + this.taskExecutor = taskExecutor; + } + + @Parameterized.Parameters(name = "{0}") + public static Collection permuteTasks() throws Exception { + List tasksToBeExecuted = new ArrayList<>(); + + MaintenanceTaskConfiguration config = new MaintenanceTaskConfiguration(); + // No need to add cron syntax as TaskExecutor class doesn't depend on cron syntax. + List maintenanceTasks = config.getMaintenanceTasks(); + for (Task task : maintenanceTasks) { + Object[] currentTaskData = {new TaskExecutor(task)}; + tasksToBeExecuted.add(currentTaskData); + } + + return tasksToBeExecuted; + } + + + @Test + public void testGetGitClient(){ + Jenkins jenkins = Jenkins.getInstanceOrNull(); + + // taskExecutor.getGitClient(); + } } From 45b1a6481186b4a4e53836b34c12a6a988839aa5 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 23 Jun 2022 22:49:41 +0530 Subject: [PATCH 037/146] fixed NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE spotbug issue --- .../java/jenkins/plugins/git/AbstractGitSCMSource.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java index 97bf938911..5e1806cde3 100644 --- a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java +++ b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java @@ -174,9 +174,11 @@ public abstract class AbstractGitSCMSource extends SCMSource { Jenkins jenkins = Jenkins.getInstanceOrNull(); if(jenkins != null){ File[] caches = new File(jenkins.getRootDir(),"caches").listFiles(); - for(File cache : caches){ - String cacheEntry = cache.getName(); - cacheEntries.add(cacheEntry); + if(caches != null) { + for (File cache : caches) { + String cacheEntry = cache.getName(); + cacheEntries.add(cacheEntry); + } } } } From 79ee4abdfc1889b93c7e11872db9a3df961ae2af Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Fri, 24 Jun 2022 02:29:59 +0530 Subject: [PATCH 038/146] added Parameterized class to TestExecutorTest --- .../java/jenkins/plugins/git/maintenance/TaskExecutorTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java index bdfd7aca44..cfab9a6a4d 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java @@ -4,6 +4,7 @@ import jenkins.model.Jenkins; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import java.io.File; @@ -12,6 +13,7 @@ import java.util.Collection; import java.util.List; +@RunWith(Parameterized.class) public class TaskExecutorTest { TaskExecutor taskExecutor; From ec598ba0ccf9951e01faca587c96ba5dddd747eb Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Fri, 24 Jun 2022 03:02:45 +0530 Subject: [PATCH 039/146] test to create executor thread --- .../git/maintenance/TaskSchedulerTest.java | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java index 53e61f0e3b..3c0a0818a8 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java @@ -12,6 +12,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; public class TaskSchedulerTest { @@ -29,6 +30,7 @@ public void setUp() throws Exception { } + // Tested all the internal functions of this method @Test public void testScheduleTasks() throws ANTLRException { taskScheduler.scheduleTasks(); @@ -82,9 +84,27 @@ public void testIsGitMaintenanceTaskRunning(){ assertFalse(isGitMaintenanceTaskRunning); } + @Test + public void testCreateNoExecutorThread() throws Exception{ + config.setCronSyntax(TaskType.PREFETCH,"5 1 1 1 1"); + config.setIsTaskConfigured(TaskType.PREFETCH,true); - // Need to think about this logic for testing. Issue while creating the thread - public void testCreateExecutorThread(){ + List maintenanceTasks = config.getMaintenanceTasks(); + taskScheduler.addTasksToQueue(maintenanceTasks); + taskScheduler.createTaskExecutorThread(); + assertNull(taskScheduler.taskExecutor); } + + @Test + public void testCreateExecutionThread() throws Exception{ + + config.setCronSyntax(TaskType.PREFETCH,"* * * * *"); + config.setIsTaskConfigured(TaskType.PREFETCH,true); + + List maintenanceTasks = config.getMaintenanceTasks(); + taskScheduler.addTasksToQueue(maintenanceTasks); + taskScheduler.createTaskExecutorThread(); + assertTrue(taskScheduler.taskExecutor.isAlive()); + } } From 149550f59f4cfd131e81e9bead299c55ad5350fb Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Fri, 24 Jun 2022 03:36:03 +0530 Subject: [PATCH 040/146] removed synchronization on queue --- .../plugins/git/maintenance/TaskScheduler.java | 2 +- .../plugins/git/maintenance/TaskExecutorTest.java | 13 +++++-------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index 154a01306d..9c24dea8b8 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -18,7 +18,7 @@ public class TaskScheduler { public TaskScheduler(){ this.config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); this.cal = new GregorianCalendar(); - this.maintenanceQueue = Collections.synchronizedList(new LinkedList()); + this.maintenanceQueue = new LinkedList(); } public void scheduleTasks() throws ANTLRException { diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java index cfab9a6a4d..437ef57bc8 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java @@ -3,9 +3,11 @@ import antlr.ANTLRException; import jenkins.model.Jenkins; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import org.jvnet.hudson.test.JenkinsRule; import java.io.File; import java.lang.reflect.Executable; @@ -16,6 +18,9 @@ @RunWith(Parameterized.class) public class TaskExecutorTest { + @Rule + public JenkinsRule j = new JenkinsRule(); + TaskExecutor taskExecutor; public TaskExecutorTest(TaskExecutor taskExecutor){ @@ -36,12 +41,4 @@ public static Collection permuteTasks() throws Exception { return tasksToBeExecuted; } - - - @Test - public void testGetGitClient(){ - Jenkins jenkins = Jenkins.getInstanceOrNull(); - - // taskExecutor.getGitClient(); - } } From b9a5fdbab4dba5288ce7cda89a92071e220df793 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Sun, 26 Jun 2022 05:29:32 +0530 Subject: [PATCH 041/146] tests for fetching git caches on jenkins controller --- .../git/maintenance/GitMaintenanceSCM.java | 4 +- .../maintenance/GitMaintenanceSCMTest.java | 76 ++++++++++++++++--- .../git/maintenance/TaskExecutorTest.java | 31 +------- 3 files changed, 71 insertions(+), 40 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java b/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java index f56f17dc82..40de63a95f 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java +++ b/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java @@ -60,7 +60,7 @@ public static List getCaches(){ return caches; } - static File getCacheDirectory(String cacheEntry,boolean createDirectory){ - return getCacheDir(cacheEntry,createDirectory); + String getCacheEntryForTest(){ + return getCacheEntry(); } } diff --git a/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java b/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java index b06c2b8198..69ccb780aa 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java @@ -1,31 +1,89 @@ package jenkins.plugins.git.maintenance; +import hudson.plugins.git.BranchSpec; +import hudson.plugins.git.GitSCM; +import hudson.plugins.git.extensions.GitSCMExtension; import jenkins.plugins.git.GitSampleRepoRule; -import org.junit.Before; +import jenkins.scm.api.SCMFileSystem; import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.JenkinsRule; +import java.io.File; +import java.util.Collections; import java.util.List; +import java.util.concurrent.locks.Lock; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; public class GitMaintenanceSCMTest { @Rule - public GitSampleRepoRule sampleRepo = new GitSampleRepoRule(); + public GitSampleRepoRule sampleRepo1 = new GitSampleRepoRule(); + + @Rule + public GitSampleRepoRule sampleRepo2 = new GitSampleRepoRule(); @Rule public JenkinsRule j = new JenkinsRule(); - @Before - public void setUp() throws Exception { - // Need to create git caches on Jenkins controller. + @Test + public void testGetCaches() throws Exception{ + sampleRepo1.init(); + sampleRepo1.git("checkout", "-b", "bug/JENKINS-42817"); + sampleRepo1.write("file", "modified"); + sampleRepo1.git("commit", "--all", "--message=dev"); + SCMFileSystem.of(j.createFreeStyleProject(), new GitSCM(GitSCM.createRepoList(sampleRepo1.toString(), null), Collections.singletonList(new BranchSpec("*/bug/JENKINS-42817")), null, null, Collections.emptyList())); + + sampleRepo2.init(); + sampleRepo2.git("checkout", "-b", "bug/JENKINS-42817"); + sampleRepo2.write("file", "modified"); + sampleRepo2.git("commit", "--all", "--message=dev"); + SCMFileSystem.of(j.createFreeStyleProject(), new GitSCM(GitSCM.createRepoList(sampleRepo2.toString(), null), Collections.singletonList(new BranchSpec("*/bug/JENKINS-42817")), null, null, Collections.emptyList())); - } + GitMaintenanceSCM[] gitMaintenanceSCMS = new GitMaintenanceSCM[2]; + gitMaintenanceSCMS[0] = new GitMaintenanceSCM(sampleRepo1.toString()); + gitMaintenanceSCMS[1] = new GitMaintenanceSCM(sampleRepo2.toString()); - @Test - public void testGetCaches(){ List caches = GitMaintenanceSCM.getCaches(); - // check the given caches is same as the caches present on jenkins controller. + for(GitMaintenanceSCM.Cache cache : caches){ + String cacheDir = cache.getCacheFile().getName(); + boolean cachesExists = false; + for(GitMaintenanceSCM gitMaintenanceSCM : gitMaintenanceSCMS){ + cachesExists = gitMaintenanceSCM.getCacheEntryForTest().equals(cacheDir); + if(cachesExists) + break; + } + + assertTrue(cachesExists); + } } +// +// @Test +// public void testNoCachesExistsOnJenkinsController(){ +// List caches = GitMaintenanceSCM.getCaches(); +// assertEquals(0,caches.size()); +// } +// +// @Test +// public void testGetLockAndCacheFile() throws Exception{ +// sampleRepo1.init(); +// sampleRepo1.git("checkout", "-b", "bug/JENKINS-4283423"); +// sampleRepo1.write("file", "modified"); +// sampleRepo1.git("commit", "--all", "--message=dev"); +// SCMFileSystem.of(j.createFreeStyleProject(), new GitSCM(GitSCM.createRepoList(sampleRepo1.toString(), null), Collections.singletonList(new BranchSpec("*/bug/JENKINS-4283423")), null, null, Collections.emptyList())); +// +// List caches = GitMaintenanceSCM.getCaches(); +// caches.stream().forEach(cache -> { +// assertNotNull(cache.getLock()); +// assertThat(cache.getLock(),instanceOf(Lock.class)); +// assertNotNull(cache.getCacheFile()); +// assertThat(cache.getCacheFile(),instanceOf(File.class)); +// }); +// } } diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java index 437ef57bc8..b776772737 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java @@ -1,44 +1,17 @@ package jenkins.plugins.git.maintenance; -import antlr.ANTLRException; -import jenkins.model.Jenkins; -import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; import org.jvnet.hudson.test.JenkinsRule; -import java.io.File; -import java.lang.reflect.Executable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -@RunWith(Parameterized.class) public class TaskExecutorTest { @Rule public JenkinsRule j = new JenkinsRule(); - TaskExecutor taskExecutor; + @Test + public void testGitClient(){ - public TaskExecutorTest(TaskExecutor taskExecutor){ - this.taskExecutor = taskExecutor; - } - - @Parameterized.Parameters(name = "{0}") - public static Collection permuteTasks() throws Exception { - List tasksToBeExecuted = new ArrayList<>(); - - MaintenanceTaskConfiguration config = new MaintenanceTaskConfiguration(); - // No need to add cron syntax as TaskExecutor class doesn't depend on cron syntax. - List maintenanceTasks = config.getMaintenanceTasks(); - for (Task task : maintenanceTasks) { - Object[] currentTaskData = {new TaskExecutor(task)}; - tasksToBeExecuted.add(currentTaskData); - } - - return tasksToBeExecuted; } } From 206427cc0214f7c5e34c30c6cc23720ce58d4abc Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Sun, 26 Jun 2022 20:22:41 +0530 Subject: [PATCH 042/146] added taskExecutorTests --- .../git/maintenance/TaskExecutorTest.java | 56 ++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java index b776772737..2b55dd3d3d 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java @@ -1,17 +1,71 @@ package jenkins.plugins.git.maintenance; +import antlr.ANTLRException; +import hudson.plugins.git.BranchSpec; +import hudson.plugins.git.GitSCM; +import jenkins.plugins.git.GitSampleRepoRule; +import jenkins.scm.api.SCMFileSystem; +import org.jenkinsci.plugins.gitclient.GitClient; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.JenkinsRule; +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertNotNull; public class TaskExecutorTest { @Rule public JenkinsRule j = new JenkinsRule(); + @Rule + public GitSampleRepoRule sampleRepo1 = new GitSampleRepoRule(); + + TaskExecutor taskExecutor; + + @Before + public void setUp() throws Exception{ + // Tested for a single maintenance tasks. Do I have to test for all maintenance tasks? + MaintenanceTaskConfiguration config = new MaintenanceTaskConfiguration(); + config.setIsTaskConfigured(TaskType.COMMIT_GRAPH,true); + config.setCronSyntax(TaskType.COMMIT_GRAPH,"* * * * *"); + List tasks = config.getMaintenanceTasks().stream().filter(Task::getIsTaskConfigured).collect(Collectors.toList()); + Task configuredTask = tasks.get(0); + + taskExecutor = new TaskExecutor(configuredTask); + + sampleRepo1.init(); + sampleRepo1.git("checkout", "-b", "bug/JENKINS-42817"); + sampleRepo1.write("file", "modified"); + sampleRepo1.git("commit", "--all", "--message=dev"); + SCMFileSystem.of(j.createFreeStyleProject(), new GitSCM(GitSCM.createRepoList(sampleRepo1.toString(), null), Collections.singletonList(new BranchSpec("*/bug/JENKINS-42817")), null, null, Collections.emptyList())); + } + @Test - public void testGitClient(){ + public void testGitClient() throws IOException, InterruptedException { + // Get directory of a single cache. + GitMaintenanceSCM.Cache cache = taskExecutor.getCaches().get(0); + File cacheFile = cache.getCacheFile(); + assertNotNull(taskExecutor.getGitClient(cacheFile)); + assertThat(taskExecutor.getGitClient(cacheFile),instanceOf(GitClient.class)); + } + @Test + public void testExecuteMaintenanceTask(){ + return; } + + @Test + public void testRun(){ + return; + } + } From 80c5f01fa4fdabb173cc79eb810f3b4d30123fba Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Tue, 28 Jun 2022 15:22:13 +0530 Subject: [PATCH 043/146] invalid cronSyntax is stored in file --- .../MaintenanceTaskConfiguration.java | 2 +- .../git/maintenance/MaintenanceUI.java | 5 -- .../jenkins/plugins/git/maintenance/Task.java | 18 +------ .../plugins/git/maintenance/TaskTest.java | 50 +------------------ 4 files changed, 4 insertions(+), 71 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java index 0d862dd3be..03e5ddebcc 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java @@ -45,7 +45,7 @@ public List getMaintenanceTasks(){ return ImmutableList.copyOf(maintenanceTasks); } - public void setCronSyntax(TaskType taskType, String cronSyntax) throws ANTLRException { + public void setCronSyntax(TaskType taskType, String cronSyntax){ Task updatedTask = maintenanceTasks.get(taskType); updatedTask.setCronSyntax(cronSyntax); maintenanceTasks.put(taskType,updatedTask); diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index 67ee7376b6..30852fe810 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -60,7 +60,6 @@ public void doSave(StaplerRequest req, StaplerResponse res) throws IOException, JSONObject formData = req.getSubmittedForm(); MaintenanceTaskConfiguration config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); - try{ assert config != null; for (TaskType taskType : TaskType.values()) { JSONObject maintenanceData = formData.getJSONObject(taskType.toString()); @@ -74,10 +73,6 @@ public void doSave(StaplerRequest req, StaplerResponse res) throws IOException, config.save(); System.out.println("Saving"); res.sendRedirect(""); - }catch (ANTLRException e){ - // Throw antlr exception and display error on UI. - System.out.println("Invalid cron syntax, will display error on screen"); - } } diff --git a/src/main/java/jenkins/plugins/git/maintenance/Task.java b/src/main/java/jenkins/plugins/git/maintenance/Task.java index d591e26ce2..e3ef9844a4 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Task.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Task.java @@ -1,11 +1,6 @@ package jenkins.plugins.git.maintenance; import antlr.ANTLRException; -import hudson.scheduler.CronTab; -import hudson.scheduler.CronTabList; - -import java.util.Calendar; -import java.util.Collections; public class Task { @@ -13,8 +8,6 @@ public class Task { private String cronSyntax; private boolean isConfigured; - private CronTabList cronTabList; - public Task(TaskType task){ // Can add default cron syntax recommended by git documentation this.task = task; @@ -45,16 +38,7 @@ public boolean getIsTaskConfigured(){ return this.isConfigured; } - public void setCronSyntax(String cronSyntax) throws ANTLRException { + public void setCronSyntax(String cronSyntax){ this.cronSyntax = cronSyntax; - setCronTabList(cronSyntax); - } - - private void setCronTabList(String cronSyntax) throws ANTLRException { - cronTabList = new CronTabList(Collections.singletonList(new CronTab(cronSyntax))); - } - - public boolean checkIsTaskExecutable(Calendar cal){ - return cronTabList.check(cal); } } diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskTest.java index 988354e06a..0a96aa9d8d 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskTest.java @@ -5,9 +5,7 @@ import org.junit.runners.Parameterized; import java.util.ArrayList; -import java.util.Calendar; import java.util.Collection; -import java.util.GregorianCalendar; import java.util.List; import static org.junit.Assert.assertFalse; @@ -56,30 +54,12 @@ public void setIsConfigured() { } @Test - public void checkCronSyntax() throws Exception { + public void checkCronSyntax(){ String cronSyntax = "* * 1 * 1"; task.setCronSyntax(cronSyntax); assertThat(task.getCronSyntax(), is(cronSyntax)); } - @Test - public void isTaskExecutable() throws Exception { - Calendar cal = new GregorianCalendar(); - String cronSyntax = "* * * * *"; - task.setCronSyntax(cronSyntax); - boolean isTaskExecutable = task.checkIsTaskExecutable(cal); - assertTrue(isTaskExecutable); - } - - @Test - public void isTaskExecutableWithHSyntax() throws Exception { - Calendar cal = new GregorianCalendar(); - String cronSyntax = "H * * * *"; - task.setCronSyntax(cronSyntax); - boolean isTaskExecutable = task.checkIsTaskExecutable(cal); - assertFalse(isTaskExecutable); - } - @Test public void testGetTaskType() { assertThat(task.getTaskType(), is(taskType)); @@ -91,7 +71,7 @@ public void testGetTaskName() { } @Test - public void testGetCronSyntax() throws Exception { + public void testGetCronSyntax(){ String cronSyntax = "* * 1 * 1"; task.setCronSyntax(cronSyntax); assertThat(task.getCronSyntax(), is(cronSyntax)); @@ -114,30 +94,4 @@ public void testGetIsTaskConfiguredFalse() { task.setIsTaskConfigured(false); assertFalse(task.getIsTaskConfigured()); } - - // Syntax not yet supported by this class - // Should parameterize test for cron syntax as well - // @Test - public void testSetCronSyntaxDaily() throws Exception { - Calendar cal = new GregorianCalendar(); - task.setCronSyntax("@daily"); - assertTrue(task.checkIsTaskExecutable(cal)); - } - - // Should parameterize test for cron syntax as well - @Test - public void testCheckIsTaskExecutable() throws Exception { - Calendar cal = new GregorianCalendar(); - String cronSyntax = "* * * * *"; - task.setCronSyntax(cronSyntax); - assertTrue(task.checkIsTaskExecutable(cal)); - } - - // Should parameterize test for cron syntax as well - @Test - public void testCheckIsTaskExecutableWithHSyntax() throws Exception { - Calendar cal = new GregorianCalendar(); - task.setCronSyntax("H * * * *"); - assertFalse(task.checkIsTaskExecutable(cal)); - } } From 2655691be732780cbee6cf90a843de9de52ee3ab Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Tue, 28 Jun 2022 15:23:13 +0530 Subject: [PATCH 044/146] verifying cron syntax during execution of maintenance tasks --- .../jenkins/plugins/git/maintenance/Cron.java | 5 +-- .../git/maintenance/TaskScheduler.java | 38 +++++++++++++++---- .../git/maintenance/TaskSchedulerTest.java | 38 +++++++++++++++++++ 3 files changed, 71 insertions(+), 10 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/Cron.java b/src/main/java/jenkins/plugins/git/maintenance/Cron.java index b309e81126..2767bbf0d5 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Cron.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Cron.java @@ -1,6 +1,5 @@ package jenkins.plugins.git.maintenance; -import antlr.ANTLRException; import hudson.Extension; import hudson.model.PeriodicWork; @@ -23,11 +22,11 @@ public long getRecurrencePeriod() { } @Override - protected void doRun() throws Exception { + protected void doRun(){ scheduleMaintenanceTask(); } - private void scheduleMaintenanceTask() throws ANTLRException { + private void scheduleMaintenanceTask(){ if(taskScheduler == null){ taskScheduler = new TaskScheduler(); } diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index 9c24dea8b8..6cec81afbf 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -1,6 +1,8 @@ package jenkins.plugins.git.maintenance; import antlr.ANTLRException; +import hudson.scheduler.CronTab; +import hudson.scheduler.CronTabList; import jenkins.model.GlobalConfiguration; import java.util.Calendar; @@ -21,17 +23,23 @@ public TaskScheduler(){ this.maintenanceQueue = new LinkedList(); } - public void scheduleTasks() throws ANTLRException { + public void scheduleTasks() { assert config != null; if(!isGitMaintenanceTaskRunning(config)) return; - List configuredTasks = config.getMaintenanceTasks(); - addTasksToQueue(configuredTasks); + try { + List configuredTasks = config.getMaintenanceTasks(); + addTasksToQueue(configuredTasks); - // Option of Using the same thread for executing more maintenance task, or create a new thread the next minute and execute the maintenance task. - createTaskExecutorThread(); + // Option of Using the same thread for executing more maintenance task, or create a new thread the next minute and execute the maintenance task. + createTaskExecutorThread(); + + }catch (ANTLRException e){ + // Log the error to a log file... + + } System.out.println(taskExecutor.isAlive() + " Status of execution after"); } @@ -45,16 +53,18 @@ void createTaskExecutorThread() throws ANTLRException { Task currentTask = maintenanceQueue.remove(0); taskExecutor = new Thread(new TaskExecutor(currentTask), "maintenance-task-executor"); taskExecutor.start(); + System.out.println("Executing maintenance task " + currentTask.getTaskName()); } } - void addTasksToQueue(List configuredTasks){ + void addTasksToQueue(List configuredTasks) throws ANTLRException { boolean isTaskExecutable; for(Task task : configuredTasks){ if(!task.getIsTaskConfigured() || checkIsTaskInQueue(task)) continue; - isTaskExecutable = task.checkIsTaskExecutable(cal); + CronTabList cronTabList = getCronTabList(task.getCronSyntax()); + isTaskExecutable = checkIsTaskExecutable(cronTabList); if(isTaskExecutable){ maintenanceQueue.add(task); } @@ -64,4 +74,18 @@ void addTasksToQueue(List configuredTasks){ boolean isGitMaintenanceTaskRunning(MaintenanceTaskConfiguration config){ return config.getIsGitMaintenanceRunning(); } + + CronTabList getCronTabList(String cronSyntax) throws ANTLRException { + CronTab cronTab = new CronTab(cronSyntax.trim()); + return new CronTabList(Collections.singletonList(cronTab)); + } + + boolean checkIsTaskExecutable(CronTabList cronTabList){ + boolean isTaskExecutable = false; + + isTaskExecutable = cronTabList.check(cal); + // Further validation such as not schedule a task every minute etc. can be added here. + + return isTaskExecutable; + } } diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java index 3c0a0818a8..8201ed6e4f 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java @@ -1,17 +1,20 @@ package jenkins.plugins.git.maintenance; import antlr.ANTLRException; +import hudson.scheduler.CronTabList; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.JenkinsRule; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -107,4 +110,39 @@ public void testCreateExecutionThread() throws Exception{ taskScheduler.createTaskExecutorThread(); assertTrue(taskScheduler.taskExecutor.isAlive()); } + + @Test + public void testCorrectCronSyntaxInput() throws ANTLRException{ + List correctCronSyntax = new ArrayList<>(); + correctCronSyntax.add("H * * * *"); + correctCronSyntax.add("* * * * *"); + correctCronSyntax.add("@hourly"); + correctCronSyntax.add("@weekly"); + correctCronSyntax.add("@daily"); + correctCronSyntax.add("H H 1,15 1-11 *"); + + for(String cronSyntax : correctCronSyntax){ + CronTabList cronTabList = taskScheduler.getCronTabList(cronSyntax); + assertNotNull(cronTabList); + } + } + + @Test(expected = ANTLRException.class) + public void testIncorrectCronSyntaxInput() throws ANTLRException{ + List incorrectCronSyntax = new ArrayList<>(); + incorrectCronSyntax.add(""); + incorrectCronSyntax.add("**"); + + // Valid format is (0-59) (0–23) (1–31) (1–12) (0–7) + incorrectCronSyntax.add("60 1 1 1 1"); + incorrectCronSyntax.add("1 24 32 11 5"); + incorrectCronSyntax.add("1 1 1 1 9"); + + for(String cronSyntax : incorrectCronSyntax){ + // Should throw an exception. + taskScheduler.getCronTabList(cronSyntax); + } + + } + } From 27da7b490d55a9214336d31dc783e7f03d64a829 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Tue, 28 Jun 2022 15:24:54 +0530 Subject: [PATCH 045/146] maintain order of maintenance task --- .../plugins/git/maintenance/MaintenanceTaskConfiguration.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java index 03e5ddebcc..bcf17b0e70 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java @@ -8,6 +8,7 @@ import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -28,7 +29,7 @@ public MaintenanceTaskConfiguration(){ private void configureMaintenanceTasks(){ // check git version and based on git version, add the maintenance tasks to the list // Can add default cron syntax for maintenance tasks. - maintenanceTasks = new HashMap<>(); + maintenanceTasks = new LinkedHashMap<>(); maintenanceTasks.put(TaskType.COMMIT_GRAPH,new Task(TaskType.COMMIT_GRAPH)); maintenanceTasks.put(TaskType.PREFETCH,new Task(TaskType.PREFETCH)); From b8d1c2b2a6d7187e22d26e7c097ae12ef87a9eb2 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Wed, 29 Jun 2022 20:30:31 +0530 Subject: [PATCH 046/146] added logs to MaintenanceUI --- .../MaintenanceTaskConfiguration.java | 3 +- .../git/maintenance/MaintenanceUI.java | 61 ++++++++++--------- .../git/maintenance/TaskSchedulerTest.java | 4 +- 3 files changed, 36 insertions(+), 32 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java index bcf17b0e70..b23855dbf5 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java @@ -7,7 +7,6 @@ import jenkins.model.GlobalConfiguration; import java.util.ArrayList; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -56,7 +55,7 @@ public boolean getIsGitMaintenanceRunning(){ return isGitMaintenanceRunning; } - public void setIsGitMaintenanceRunning(){isGitMaintenanceRunning = !isGitMaintenanceRunning;} + public void setIsGitMaintenanceRunning(boolean executionStatus){isGitMaintenanceRunning = executionStatus;} public void setIsTaskConfigured(TaskType taskType, boolean isConfigured){ Task task = maintenanceTasks.get(taskType); diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index 30852fe810..aef5de34fa 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -21,10 +21,14 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; @Extension public class MaintenanceUI extends ManagementLink { + private static final Logger LOGGER = Logger.getLogger(MaintenanceUI.class.getName()); + @Override public String getIconFileName() { return jenkins.model.Jenkins.RESOURCE_PATH + "/plugin/git/icons/git-maintenance.svg"; @@ -53,6 +57,7 @@ public String getDescription() { @Restricted(NoExternalUse.class) public void doSave(StaplerRequest req, StaplerResponse res) throws IOException, ServletException { if (!Jenkins.get().hasPermission(Jenkins.ADMINISTER)) { + LOGGER.log(Level.WARNING,"User doesn't have the required permission to access git-maintenance."); res.sendError(HttpServletResponse.SC_FORBIDDEN); return; } @@ -60,37 +65,41 @@ public void doSave(StaplerRequest req, StaplerResponse res) throws IOException, JSONObject formData = req.getSubmittedForm(); MaintenanceTaskConfiguration config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); - assert config != null; - for (TaskType taskType : TaskType.values()) { - JSONObject maintenanceData = formData.getJSONObject(taskType.toString()); - String cronSyntax = maintenanceData.getString("cronSyntax"); - boolean isApplied = maintenanceData.getBoolean("isApplied"); - - // Need to perform form validation again to avoid incorrect save of data. - config.setCronSyntax(taskType, cronSyntax); - config.setIsTaskConfigured(taskType, isApplied); - } - config.save(); - System.out.println("Saving"); - res.sendRedirect(""); + // Need to check with mentors if I can use the below syntax. + assert config != null; + for (TaskType taskType : TaskType.values()) { + JSONObject maintenanceData = formData.getJSONObject(taskType.toString()); + String cronSyntax = maintenanceData.getString("cronSyntax"); + boolean isApplied = maintenanceData.getBoolean("isApplied"); + config.setCronSyntax(taskType, cronSyntax); + config.setIsTaskConfigured(taskType, isApplied); + } + config.save(); + LOGGER.log(Level.FINE,"Maintenance configuration data stored successfully on Jenkins."); + res.sendRedirect(""); } @RequirePOST @Restricted(NoExternalUse.class) public void doToggleExecutionState(StaplerRequest req, StaplerResponse res) throws IOException { if (!Jenkins.get().hasPermission(Jenkins.ADMINISTER)) { + LOGGER.log(Level.WARNING,"User doesn't have the required permission to access git-maintenance"); res.sendError(HttpServletResponse.SC_FORBIDDEN); return; } MaintenanceTaskConfiguration config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); - if(config != null) { - config.setIsGitMaintenanceRunning(); - config.save(); - } - System.out.println("Executing..."); + // Need to check with mentors if I can use the below syntax. + assert config != null; + boolean updatedGitMaintenanceExecutionStatus = !config.getIsGitMaintenanceRunning(); + config.setIsGitMaintenanceRunning(updatedGitMaintenanceExecutionStatus); + config.save(); + if(updatedGitMaintenanceExecutionStatus) + LOGGER.log(Level.FINE,"Git Maintenance tasks are scheduled for execution."); + else + LOGGER.log(Level.FINE,"Terminated scheduling of Git Maintenance tasks."); res.sendRedirect(""); } @@ -116,20 +125,16 @@ public FormValidation doCheckCronSyntax(@QueryParameter String cronSyntax) throw public List getMaintenanceTasks(){ // Can check if git version doesn't support a maintenance task and remove that maintenance task from the UI. MaintenanceTaskConfiguration config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); - if(config != null) - return config.getMaintenanceTasks(); - - // need to throw error; - return null; + // Need to check with mentors if I can use the below syntax. + assert config != null; + return config.getMaintenanceTasks(); } public boolean getIsGitMaintenanceRunning(){ MaintenanceTaskConfiguration config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); - if(config != null) - return config.getIsGitMaintenanceRunning(); - - // need to throw error; - return false; + // Need to check with mentors if I can use the below syntax. + assert config != null; + return config.getIsGitMaintenanceRunning(); } public String getGitVersion(){ diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java index 8201ed6e4f..6733f34c80 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java @@ -77,12 +77,12 @@ public void testAddTasksToQueue() throws Exception { @Test public void testIsGitMaintenanceTaskRunning(){ // Setting value to true - config.setIsGitMaintenanceRunning(); + config.setIsGitMaintenanceRunning(true); boolean isGitMaintenanceTaskRunning = taskScheduler.isGitMaintenanceTaskRunning(config); assertTrue(isGitMaintenanceTaskRunning); // set value to false - config.setIsGitMaintenanceRunning(); + config.setIsGitMaintenanceRunning(false); isGitMaintenanceTaskRunning = taskScheduler.isGitMaintenanceTaskRunning(config); assertFalse(isGitMaintenanceTaskRunning); } From cedc797d4b2c82353caee99c9285a864a0c2a4df Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 30 Jun 2022 10:54:37 +0530 Subject: [PATCH 047/146] Added logging to MaintenanceTaskConfiguration --- .../maintenance/MaintenanceTaskConfiguration.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java index b23855dbf5..18cfe08661 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java @@ -10,6 +10,8 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; @Extension public class MaintenanceTaskConfiguration extends GlobalConfiguration { @@ -17,12 +19,18 @@ public class MaintenanceTaskConfiguration extends GlobalConfiguration { private Map maintenanceTasks; private boolean isGitMaintenanceRunning; + private static final Logger LOGGER = Logger.getLogger(MaintenanceTaskConfiguration.class.getName()); + public MaintenanceTaskConfiguration(){ + LOGGER.log(Level.FINE,"Loading git-maintenance configuration if present on jenkins controller."); load(); if(maintenanceTasks == null) { + LOGGER.log(Level.FINE,"Git maintenance configuration not present on Jenkins, creating a default configuration"); configureMaintenanceTasks(); isGitMaintenanceRunning = false; + }else{ + LOGGER.log(Level.FINE,"Loaded git maintenance configuration successfully."); } } private void configureMaintenanceTasks(){ @@ -49,6 +57,7 @@ public void setCronSyntax(TaskType taskType, String cronSyntax){ Task updatedTask = maintenanceTasks.get(taskType); updatedTask.setCronSyntax(cronSyntax); maintenanceTasks.put(taskType,updatedTask); + LOGGER.log(Level.FINE,"Assigned " + cronSyntax + " to " + taskType.getTaskName()); } public boolean getIsGitMaintenanceRunning(){ @@ -60,16 +69,14 @@ public boolean getIsGitMaintenanceRunning(){ public void setIsTaskConfigured(TaskType taskType, boolean isConfigured){ Task task = maintenanceTasks.get(taskType); task.setIsTaskConfigured(isConfigured); + LOGGER.log(Level.FINE,taskType.getTaskName() + " execution status: " + isConfigured); } public static String checkSanity(String cron) throws ANTLRException { try { CronTab cronTab = new CronTab(cron.trim()); String msg = cronTab.checkSanity(); - if (msg != null) { - return msg; - } - return null; + return msg; }catch(ANTLRException e){ if(cron.contains("**")) throw new ANTLRException("You appear to be missing whitespace between * and *."); From 31eb4c2925bfa16d9adbef2c0223c71f5a9964eb Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 30 Jun 2022 11:31:49 +0530 Subject: [PATCH 048/146] added logging to TaskScheduler --- .../jenkins/plugins/git/maintenance/Task.java | 2 +- .../plugins/git/maintenance/TaskExecutor.java | 2 +- .../git/maintenance/TaskScheduler.java | 44 +++++++++++-------- 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/Task.java b/src/main/java/jenkins/plugins/git/maintenance/Task.java index e3ef9844a4..6b160bb711 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Task.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Task.java @@ -13,7 +13,7 @@ public Task(TaskType task){ this.task = task; } - public Task(Task copyTask) throws ANTLRException { + public Task(Task copyTask){ // Used for copying the task; this(copyTask.getTaskType()); setCronSyntax(copyTask.getCronSyntax()); diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index 7ed79d6816..c5c87ab5b8 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -18,7 +18,7 @@ public class TaskExecutor implements Runnable { Task maintenanceTask; List caches; - public TaskExecutor(Task maintenanceTask) throws ANTLRException { + public TaskExecutor(Task maintenanceTask){ this.maintenanceTask = new Task(maintenanceTask); caches = getCaches(); } diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index 6cec81afbf..86541848c0 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -10,6 +10,8 @@ import java.util.GregorianCalendar; import java.util.LinkedList; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; public class TaskScheduler { @@ -17,6 +19,9 @@ public class TaskScheduler { Calendar cal; List maintenanceQueue; Thread taskExecutor; + + private static final Logger LOGGER = Logger.getLogger(TaskScheduler.class.getName()); + public TaskScheduler(){ this.config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); this.cal = new GregorianCalendar(); @@ -26,47 +31,50 @@ public TaskScheduler(){ public void scheduleTasks() { assert config != null; - if(!isGitMaintenanceTaskRunning(config)) + if(!isGitMaintenanceTaskRunning(config)) { + // Logs ever 1 min. Need to check performance impact. + LOGGER.log(Level.FINER,"Maintenance Task execution not configured"); return; + } - try { List configuredTasks = config.getMaintenanceTasks(); addTasksToQueue(configuredTasks); // Option of Using the same thread for executing more maintenance task, or create a new thread the next minute and execute the maintenance task. createTaskExecutorThread(); - - }catch (ANTLRException e){ - // Log the error to a log file... - - } - System.out.println(taskExecutor.isAlive() + " Status of execution after"); } boolean checkIsTaskInQueue(Task task){ return maintenanceQueue.stream().anyMatch(queuedTask -> queuedTask.getTaskType().equals(task.getTaskType())); } - void createTaskExecutorThread() throws ANTLRException { + void createTaskExecutorThread(){ // Create a new thread and execute the tasks present in the queue; if(!maintenanceQueue.isEmpty() && (taskExecutor == null || !taskExecutor.isAlive())) { Task currentTask = maintenanceQueue.remove(0); taskExecutor = new Thread(new TaskExecutor(currentTask), "maintenance-task-executor"); taskExecutor.start(); - System.out.println("Executing maintenance task " + currentTask.getTaskName()); + LOGGER.log(Level.FINE,"Thread created to execute " + currentTask.getTaskName() + " maintenance task."); } } - void addTasksToQueue(List configuredTasks) throws ANTLRException { + void addTasksToQueue(List configuredTasks){ + boolean isTaskExecutable; for(Task task : configuredTasks){ - if(!task.getIsTaskConfigured() || checkIsTaskInQueue(task)) - continue; - - CronTabList cronTabList = getCronTabList(task.getCronSyntax()); - isTaskExecutable = checkIsTaskExecutable(cronTabList); - if(isTaskExecutable){ - maintenanceQueue.add(task); + try { + if(!task.getIsTaskConfigured() || checkIsTaskInQueue(task)) + continue; + + CronTabList cronTabList = getCronTabList(task.getCronSyntax()); + isTaskExecutable = checkIsTaskExecutable(cronTabList); + if(isTaskExecutable){ + maintenanceQueue.add(task); + LOGGER.log(Level.FINE,task.getTaskName() + " added to maintenance queue."); + } + }catch (ANTLRException e){ + // Logged every minute. Need to check performance. + LOGGER.log(Level.WARNING,"Invalid cron syntax:[ "+ task.getTaskName() + " ]" + ",msg: " + e.getMessage()); } } } From 4908181321cc8593061006288a0dd22e6e73dc3b Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 30 Jun 2022 11:58:18 +0530 Subject: [PATCH 049/146] Logging for TaskExecutor added --- .../plugins/git/maintenance/TaskExecutor.java | 29 +++++++++++-------- .../git/maintenance/TaskScheduler.java | 2 +- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index c5c87ab5b8..12945badde 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -1,6 +1,5 @@ package jenkins.plugins.git.maintenance; -import antlr.ANTLRException; import hudson.FilePath; import hudson.model.TaskListener; import hudson.plugins.git.GitTool; @@ -12,12 +11,16 @@ import java.io.IOException; import java.util.List; import java.util.concurrent.locks.Lock; +import java.util.logging.Level; +import java.util.logging.Logger; public class TaskExecutor implements Runnable { Task maintenanceTask; List caches; + private static final Logger LOGGER = Logger.getLogger(TaskExecutor.class.getName()); + public TaskExecutor(Task maintenanceTask){ this.maintenanceTask = new Task(maintenanceTask); caches = getCaches(); @@ -26,32 +29,34 @@ public TaskExecutor(Task maintenanceTask){ @Override public void run() { - System.out.println("Entered the Thread"); - // Execute Maintenance Tasks in this class. - - // TODO - + LOGGER.log(Level.FINE,"Running maintenance task " + maintenanceTask.getTaskName() + " on git caches."); GitClient gitClient; for(GitMaintenanceSCM.Cache cache : caches){ // For now adding lock to all kinds of maintenance tasks. Need to study on which task needs a lock and which doesn't. Lock lock = cache.getLock(); + File cacheFile = cache.getCacheFile(); try { - File cacheFile = cache.getCacheFile(); - System.out.println("Executing maintenance task for " + cacheFile.getName()); gitClient = getGitClient(cacheFile); + + if(gitClient == null) { + LOGGER.log(Level.WARNING,"No GitTool found while running " + maintenanceTask.getTaskName()); + return; + } + TaskType taskType = maintenanceTask.getTaskType(); lock.lock(); - System.out.println("Locked the cache"); + LOGGER.log(Level.FINE,"Cache " + cacheFile.getName() + " locked."); executeMaintenanceTask(gitClient,taskType); } catch (IOException | InterruptedException e) { - System.out.println("Need to handle error"); + // What is this error??? + LOGGER.log(Level.WARNING,"Git Client couldn't be initialized."); }finally { lock.unlock(); - System.out.println("Unlocked the cache"); + LOGGER.log(Level.FINE,"Cache " + cacheFile.getName() + " unlocked."); } } @@ -70,7 +75,7 @@ void executeMaintenanceTask(GitClient gitClient,TaskType taskType) throws Interr }else if(taskType.equals(TaskType.LOOSE_OBJECTS)){ gitClient.maintenance("loose-objects"); }else{ - // Error + LOGGER.log(Level.WARNING,"Invalid maintenance task."); } } diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index 86541848c0..87f2a0cbe3 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -54,7 +54,7 @@ void createTaskExecutorThread(){ Task currentTask = maintenanceQueue.remove(0); taskExecutor = new Thread(new TaskExecutor(currentTask), "maintenance-task-executor"); taskExecutor.start(); - LOGGER.log(Level.FINE,"Thread created to execute " + currentTask.getTaskName() + " maintenance task."); + LOGGER.log(Level.FINE,"Thread [" + taskExecutor.getName() +"] created to execute " + currentTask.getTaskName() + " maintenance task."); } } From 8d8f4e9ac983830ad0483d75732200426710c9b1 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Sat, 2 Jul 2022 15:25:16 +0530 Subject: [PATCH 050/146] fetch git version in maintenance UI --- .../MaintenanceTaskConfiguration.java | 28 +++++++++++++++++++ .../git/maintenance/MaintenanceUI.java | 14 +++++++++- .../git/maintenance/MaintenanceUI/index.jelly | 5 ++-- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java index 18cfe08661..c6e416e4af 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java @@ -3,15 +3,22 @@ import antlr.ANTLRException; import com.google.common.collect.ImmutableList; import hudson.Extension; +import hudson.Launcher; +import hudson.model.TaskListener; import hudson.scheduler.CronTab; +import hudson.util.StreamTaskListener; import jenkins.model.GlobalConfiguration; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.stream.Collectors; @Extension public class MaintenanceTaskConfiguration extends GlobalConfiguration { @@ -83,4 +90,25 @@ public static String checkSanity(String cron) throws ANTLRException { throw new ANTLRException(String.format("Invalid input: \"%s\": %s", cron, e), e); } } + + public static List getGitVersion(){ + + final TaskListener procListener = StreamTaskListener.fromStderr(); + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + try { + int returnCode = new Launcher.LocalLauncher(procListener).launch().cmds("git", "--version").stdout(out).join(); + if (returnCode != 0) { + LOGGER.log(Level.WARNING, "Command 'git --version' returned " + returnCode); + } + } catch (IOException | InterruptedException ex) { + LOGGER.log(Level.WARNING, "Exception checking git version " + ex); + } + final String versionOutput = out.toString().trim(); + final String[] fields = versionOutput.split(" ")[2].replaceAll("msysgit.", "").replaceAll("windows.", "").split("\\."); + + // 0th index is Major Version. + // 1st index is Minor Version. + // 2nd index is Patch Version. + return Arrays.stream(fields).map(Integer::parseInt).collect(Collectors.toList()); + } } diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index aef5de34fa..04bd39b81a 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -138,7 +138,19 @@ public boolean getIsGitMaintenanceRunning(){ } public String getGitVersion(){ - return "2.36.1"; + List gitVersion = MaintenanceTaskConfiguration.getGitVersion(); + return gitVersion.get(0) + "." + gitVersion.get(1) + "." + gitVersion.get(2); + } + + public String updateGitVersionHelperText(){ + List gitVersion = MaintenanceTaskConfiguration.getGitVersion(); + int gitMajor = gitVersion.get(0); + int gitMinor = gitVersion.get(1); + + if((gitMajor == 2 && gitMinor >= 30) || (gitMajor > 2)) + return ""; + + return "Use git version >= 2.30 to get full benefits of git maintenance."; } @NonNull diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly index aac9c1e841..4085fe9100 100644 --- a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly @@ -5,8 +5,9 @@

Maintenance Tasks

-

Git Version: ${it.getGitVersion()} (HardCoded Value)

-

Enter cron syntax for periodic execution of maintenance tasks

+

Git Version: ${it.getGitVersion()}

+

${it.updateGitVersionHelperText()}

+

Enter cron syntax to execute maintenance tasks periodically

From 8829576ad4aab53406c762f3f26aea8e48e15333 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Sun, 3 Jul 2022 10:31:30 +0530 Subject: [PATCH 051/146] package protected getGitVersion --- .../git/maintenance/MaintenanceTaskConfiguration.java | 2 +- .../jenkins/plugins/git/maintenance/TaskExecutor.java | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java index c6e416e4af..a1d382e33a 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java @@ -91,7 +91,7 @@ public static String checkSanity(String cron) throws ANTLRException { } } - public static List getGitVersion(){ + static List getGitVersion(){ final TaskListener procListener = StreamTaskListener.fromStderr(); final ByteArrayOutputStream out = new ByteArrayOutputStream(); diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index 12945badde..854db105a7 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -4,6 +4,7 @@ import hudson.model.TaskListener; import hudson.plugins.git.GitTool; import hudson.plugins.git.util.GitUtils; +import jenkins.model.Jenkins; import org.jenkinsci.plugins.gitclient.Git; import org.jenkinsci.plugins.gitclient.GitClient; @@ -80,6 +81,10 @@ void executeMaintenanceTask(GitClient gitClient,TaskType taskType) throws Interr } + private List getGitVersion(){ + return MaintenanceTaskConfiguration.getGitVersion(); + } + List getCaches(){ return GitMaintenanceSCM.getCaches(); } @@ -87,7 +92,9 @@ List getCaches(){ GitClient getGitClient(File file) throws IOException, InterruptedException { // What exactly is default tool here? TaskListener listener = TaskListener.NULL; - GitTool gitTool = GitUtils.resolveGitTool("Default", listener); + final Jenkins jenkins = Jenkins.getInstanceOrNull(); + // How to get Jenkins controller as the node? + GitTool gitTool = GitUtils.resolveGitTool(null,jenkins,null, listener); if(gitTool == null) return null; From d451ffc399da50910f529e9e5775cdfb2bd8685f Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Sun, 3 Jul 2022 10:53:07 +0530 Subject: [PATCH 052/146] Executing maintenance tasks only using CliGit --- .../plugins/git/maintenance/TaskExecutor.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index 854db105a7..2b2f7e0406 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -5,6 +5,7 @@ import hudson.plugins.git.GitTool; import hudson.plugins.git.util.GitUtils; import jenkins.model.Jenkins; +import org.jenkinsci.plugins.gitclient.CliGitAPIImpl; import org.jenkinsci.plugins.gitclient.Git; import org.jenkinsci.plugins.gitclient.GitClient; @@ -39,11 +40,8 @@ public void run() { File cacheFile = cache.getCacheFile(); try { gitClient = getGitClient(cacheFile); - - if(gitClient == null) { - LOGGER.log(Level.WARNING,"No GitTool found while running " + maintenanceTask.getTaskName()); + if(gitClient == null) return; - } TaskType taskType = maintenanceTask.getTaskType(); @@ -95,13 +93,20 @@ GitClient getGitClient(File file) throws IOException, InterruptedException { final Jenkins jenkins = Jenkins.getInstanceOrNull(); // How to get Jenkins controller as the node? GitTool gitTool = GitUtils.resolveGitTool(null,jenkins,null, listener); - if(gitTool == null) + if(gitTool == null) { + LOGGER.log(Level.WARNING,"No GitTool found while running " + maintenanceTask.getTaskName()); return null; + } String gitExe = gitTool.getGitExe(); FilePath workspace = new FilePath(file); Git git = Git.with(listener,null).in(workspace).using(gitExe); - return git.getClient(); + GitClient gitClient = git.getClient(); + if(gitClient instanceof CliGitAPIImpl) + return gitClient; + + LOGGER.log(Level.WARNING,"Cli Git is not being used to execute maintenance tasks"); + return null; } } From b3cbab2b1cc69848cc1b1a4d9207a1ebbe462357 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Sun, 3 Jul 2022 11:11:41 +0530 Subject: [PATCH 053/146] Added LogTaskListener --- .../java/jenkins/plugins/git/maintenance/TaskExecutor.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index 2b2f7e0406..53dfd2bedb 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -4,6 +4,7 @@ import hudson.model.TaskListener; import hudson.plugins.git.GitTool; import hudson.plugins.git.util.GitUtils; +import hudson.util.LogTaskListener; import jenkins.model.Jenkins; import org.jenkinsci.plugins.gitclient.CliGitAPIImpl; import org.jenkinsci.plugins.gitclient.Git; @@ -89,7 +90,7 @@ List getCaches(){ GitClient getGitClient(File file) throws IOException, InterruptedException { // What exactly is default tool here? - TaskListener listener = TaskListener.NULL; + TaskListener listener = new LogTaskListener(LOGGER,Level.FINE); final Jenkins jenkins = Jenkins.getInstanceOrNull(); // How to get Jenkins controller as the node? GitTool gitTool = GitUtils.resolveGitTool(null,jenkins,null, listener); From efaf64468d3dc593325b4cedb4e80ad2e2a1e1cc Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 7 Jul 2022 02:01:31 +0530 Subject: [PATCH 054/146] Logic to terminate TaskExecutorThread and clear MaintenanceQueue --- .../java/jenkins/plugins/git/maintenance/Cron.java | 6 ++++++ .../plugins/git/maintenance/MaintenanceUI.java | 11 ++++++++--- .../plugins/git/maintenance/TaskScheduler.java | 7 ++++++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/Cron.java b/src/main/java/jenkins/plugins/git/maintenance/Cron.java index 2767bbf0d5..197891b211 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Cron.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Cron.java @@ -26,6 +26,12 @@ protected void doRun(){ scheduleMaintenanceTask(); } + void terminateMaintenanceTaskExecution(){ + if(taskScheduler != null){ + taskScheduler.terminateMaintenanceTaskExecution(); + } + } + private void scheduleMaintenanceTask(){ if(taskScheduler == null){ taskScheduler = new TaskScheduler(); diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index 04bd39b81a..731e1ec04f 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -4,6 +4,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; import hudson.Extension; import hudson.model.ManagementLink; +import hudson.model.PeriodicWork; import hudson.security.Permission; import hudson.util.FormValidation; import jenkins.model.GlobalConfiguration; @@ -98,8 +99,13 @@ public void doToggleExecutionState(StaplerRequest req, StaplerResponse res) thro config.save(); if(updatedGitMaintenanceExecutionStatus) LOGGER.log(Level.FINE,"Git Maintenance tasks are scheduled for execution."); - else - LOGGER.log(Level.FINE,"Terminated scheduling of Git Maintenance tasks."); + else { + Cron cron = PeriodicWork.all().get(Cron.class); + assert cron != null; + cron.terminateMaintenanceTaskExecution(); + cron.cancel(); + LOGGER.log(Level.FINE, "Terminated scheduling of Git Maintenance tasks."); + } res.sendRedirect(""); } @@ -158,5 +164,4 @@ public String updateGitVersionHelperText(){ public Permission getRequiredPermission() { return Jenkins.ADMINISTER; } - } diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index 87f2a0cbe3..cbb52330d7 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -39,7 +39,6 @@ public void scheduleTasks() { List configuredTasks = config.getMaintenanceTasks(); addTasksToQueue(configuredTasks); - // Option of Using the same thread for executing more maintenance task, or create a new thread the next minute and execute the maintenance task. createTaskExecutorThread(); } @@ -96,4 +95,10 @@ boolean checkIsTaskExecutable(CronTabList cronTabList){ return isTaskExecutable; } + + void terminateMaintenanceTaskExecution(){ + this.maintenanceQueue = new LinkedList<>(); + if(taskExecutor.isAlive()) + taskExecutor.interrupt(); + } } From b8777934a33c5814d4cd05119752d580bbb08e65 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 7 Jul 2022 02:18:06 +0530 Subject: [PATCH 055/146] Logging caches on Controller to debug tmp caches --- src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java | 1 + .../jenkins/plugins/git/maintenance/GitMaintenanceSCM.java | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java index 5e1806cde3..b8bf2510f9 100644 --- a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java +++ b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java @@ -180,6 +180,7 @@ public abstract class AbstractGitSCMSource extends SCMSource { cacheEntries.add(cacheEntry); } } + LOGGER.log(Level.FINE,"Caches on Jenkins controller " + cacheEntries); } } diff --git a/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java b/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java index 40de63a95f..8007819009 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java +++ b/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java @@ -7,10 +7,14 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.locks.Lock; +import java.util.logging.Level; +import java.util.logging.Logger; public class GitMaintenanceSCM extends AbstractGitSCMSource { String remote; + + private static Logger LOGGER = Logger.getLogger(GitMaintenanceSCM.class.getName()); protected GitMaintenanceSCM(String remote){ this.remote = remote; } @@ -54,6 +58,7 @@ public static List getCaches(){ for (String cacheEntry : getCacheEntries()) { File cacheDir = getCacheDir(cacheEntry); Lock cacheLock = getCacheLock(cacheEntry); + LOGGER.log(Level.FINE,"Cache Entry " + cacheEntry); caches.add(new Cache(cacheDir,cacheLock)); } From 3aea0d04d8f9860276f617e25211517c5d359db0 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 7 Jul 2022 14:35:25 +0530 Subject: [PATCH 056/146] updated logs --- .../java/jenkins/plugins/git/maintenance/Cron.java | 2 +- .../plugins/git/maintenance/TaskExecutor.java | 7 +++++-- .../plugins/git/maintenance/TaskScheduler.java | 13 ++++++++++--- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/Cron.java b/src/main/java/jenkins/plugins/git/maintenance/Cron.java index 197891b211..d45e9e4dda 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Cron.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Cron.java @@ -9,7 +9,7 @@ @Extension public class Cron extends PeriodicWork { - TaskScheduler taskScheduler; + private TaskScheduler taskScheduler; @Override public long getInitialDelay(){ diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index 53dfd2bedb..a04a4f2233 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -27,12 +27,13 @@ public class TaskExecutor implements Runnable { public TaskExecutor(Task maintenanceTask){ this.maintenanceTask = new Task(maintenanceTask); caches = getCaches(); + LOGGER.log(Level.FINE,"New Thread created to execute " + maintenanceTask.getTaskName()); } @Override public void run() { - LOGGER.log(Level.FINE,"Running maintenance task " + maintenanceTask.getTaskName() + " on git caches."); + LOGGER.log(Level.FINE,"Executing maintenance task " + maintenanceTask.getTaskName() + " on git caches."); GitClient gitClient; for(GitMaintenanceSCM.Cache cache : caches){ @@ -85,7 +86,9 @@ private List getGitVersion(){ } List getCaches(){ - return GitMaintenanceSCM.getCaches(); + List caches = GitMaintenanceSCM.getCaches(); + LOGGER.log(Level.FINE,"Fetched all caches present on Jenkins Controller."); + return caches; } GitClient getGitClient(File file) throws IOException, InterruptedException { diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index cbb52330d7..64e0e1b73e 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -26,6 +26,7 @@ public TaskScheduler(){ this.config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); this.cal = new GregorianCalendar(); this.maintenanceQueue = new LinkedList(); + LOGGER.log(Level.FINE,"TaskScheduler class Initialized."); } public void scheduleTasks() { @@ -33,7 +34,7 @@ public void scheduleTasks() { if(!isGitMaintenanceTaskRunning(config)) { // Logs ever 1 min. Need to check performance impact. - LOGGER.log(Level.FINER,"Maintenance Task execution not configured"); + LOGGER.log(Level.FINER,"Maintenance Task execution not configured in UI."); return; } @@ -44,7 +45,11 @@ public void scheduleTasks() { } boolean checkIsTaskInQueue(Task task){ - return maintenanceQueue.stream().anyMatch(queuedTask -> queuedTask.getTaskType().equals(task.getTaskType())); + boolean isTaskInQueue = maintenanceQueue.stream().anyMatch(queuedTask -> queuedTask.getTaskType().equals(task.getTaskType())); + if(isTaskInQueue){ + LOGGER.log(Level.FINE,task.getTaskName() + " is already present in maintenance queue."); + } + return isTaskInQueue; } void createTaskExecutorThread(){ @@ -53,7 +58,7 @@ void createTaskExecutorThread(){ Task currentTask = maintenanceQueue.remove(0); taskExecutor = new Thread(new TaskExecutor(currentTask), "maintenance-task-executor"); taskExecutor.start(); - LOGGER.log(Level.FINE,"Thread [" + taskExecutor.getName() +"] created to execute " + currentTask.getTaskName() + " maintenance task."); + LOGGER.log(Level.FINE,"Thread [" + taskExecutor.getName() +"] created to execute " + currentTask.getTaskName() + " task."); } } @@ -100,5 +105,7 @@ void terminateMaintenanceTaskExecution(){ this.maintenanceQueue = new LinkedList<>(); if(taskExecutor.isAlive()) taskExecutor.interrupt(); + + LOGGER.log(Level.FINE,"Terminated Execution of maintenance tasks"); } } From 1e3dc7aa3e3d74c033e7a45cf22be0deeea49900 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 7 Jul 2022 16:05:05 +0530 Subject: [PATCH 057/146] init legacy git maintenance --- .../MaintenanceTaskConfiguration.java | 24 +++++++++++++++++++ .../plugins/git/maintenance/TaskExecutor.java | 15 ++++++++++-- .../git/maintenance/TaskSchedulerTest.java | 1 - 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java index a1d382e33a..cda9eacdd0 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java @@ -8,6 +8,7 @@ import hudson.scheduler.CronTab; import hudson.util.StreamTaskListener; import jenkins.model.GlobalConfiguration; +import org.apache.commons.lang3.StringUtils; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -111,4 +112,27 @@ static List getGitVersion(){ // 2nd index is Patch Version. return Arrays.stream(fields).map(Integer::parseInt).collect(Collectors.toList()); } + + + public static boolean gitVersionAtLeast(int neededMajor, int neededMinor, int neededPatch) { + List fields = getGitVersion(); + final int gitMajor = fields.get(0); + final int gitMinor = fields.get(1); + final int gitPatch = fields.get(2); + + final String versionOutput = StringUtils.join(fields,"."); + if (gitMajor < 1 || gitMajor > 3) { + LOGGER.log(Level.WARNING, "Unexpected git major version " + gitMajor + " parsed from '" + versionOutput + "', field:'" + fields.get(0) + "'"); + } + if (gitMinor < 0 || gitMinor > 50) { + LOGGER.log(Level.WARNING, "Unexpected git minor version " + gitMinor + " parsed from '" + versionOutput + "', field:'" + fields.get(1) + "'"); + } + if (gitPatch < 0 || gitPatch > 20) { + LOGGER.log(Level.WARNING, "Unexpected git patch version " + gitPatch + " parsed from '" + versionOutput + "', field:'" + fields.get(2) + "'"); + } + + return gitMajor > neededMajor || + (gitMajor == neededMajor && gitMinor > neededMinor) || + (gitMajor == neededMajor && gitMinor == neededMinor && gitPatch >= neededPatch); + } } diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index a04a4f2233..c77124d278 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -65,6 +65,15 @@ public void run() { void executeMaintenanceTask(GitClient gitClient,TaskType taskType) throws InterruptedException{ + if(gitVersionAtLeast(2,30,0)){ + executeGitMaintenance(gitClient,taskType); + }else{ + executeLegacyGitMaintenance(gitClient,taskType); + } + } + + void executeGitMaintenance(GitClient gitClient,TaskType taskType) throws InterruptedException { + if(taskType.equals(TaskType.GC)){ gitClient.maintenance("gc"); }else if(taskType.equals(TaskType.COMMIT_GRAPH)){ @@ -78,11 +87,13 @@ void executeMaintenanceTask(GitClient gitClient,TaskType taskType) throws Interr }else{ LOGGER.log(Level.WARNING,"Invalid maintenance task."); } + } + void executeLegacyGitMaintenance(GitClient gitClient,TaskType taskType){ } - private List getGitVersion(){ - return MaintenanceTaskConfiguration.getGitVersion(); + private boolean gitVersionAtLeast(int neededMajor, int neededMinor, int neededPatch){ + return MaintenanceTaskConfiguration.gitVersionAtLeast(neededMajor,neededMinor,neededPatch); } List getCaches(){ diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java index 6733f34c80..4931cf315b 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java @@ -142,7 +142,6 @@ public void testIncorrectCronSyntaxInput() throws ANTLRException{ // Should throw an exception. taskScheduler.getCronTabList(cronSyntax); } - } } From 80806391d913702e7852aadbeeef3be35cb1e674 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 7 Jul 2022 17:10:16 +0530 Subject: [PATCH 058/146] added tests and made few fields private --- .../plugins/git/maintenance/TaskExecutor.java | 7 +++--- .../git/maintenance/TaskScheduler.java | 17 +++++++++---- .../maintenance/GitMaintenanceSCMTest.java | 24 +++++++++++++------ .../git/maintenance/TaskSchedulerTest.java | 14 ++++++++--- 4 files changed, 44 insertions(+), 18 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index c77124d278..01660ca434 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -20,7 +20,7 @@ public class TaskExecutor implements Runnable { Task maintenanceTask; - List caches; + private List caches; private static final Logger LOGGER = Logger.getLogger(TaskExecutor.class.getName()); @@ -73,7 +73,8 @@ void executeMaintenanceTask(GitClient gitClient,TaskType taskType) throws Interr } void executeGitMaintenance(GitClient gitClient,TaskType taskType) throws InterruptedException { - + // checking git version for every cache. Reason is because in the UI, the git version can be changed anytime. + LOGGER.log(Level.FINE,"Git version >= 2.30.0 detected. Using official git maintenance command."); if(taskType.equals(TaskType.GC)){ gitClient.maintenance("gc"); }else if(taskType.equals(TaskType.COMMIT_GRAPH)){ @@ -89,7 +90,7 @@ void executeGitMaintenance(GitClient gitClient,TaskType taskType) throws Interru } } void executeLegacyGitMaintenance(GitClient gitClient,TaskType taskType){ - + LOGGER.log(Level.FINE,"Git version < 2.30.0 detected. Using legacy git maintenance commands"); } private boolean gitVersionAtLeast(int neededMajor, int neededMinor, int neededPatch){ diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index 64e0e1b73e..92f30c2741 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -15,10 +15,10 @@ public class TaskScheduler { - MaintenanceTaskConfiguration config; - Calendar cal; - List maintenanceQueue; - Thread taskExecutor; + private MaintenanceTaskConfiguration config; + private Calendar cal; + private List maintenanceQueue; + private Thread taskExecutor; private static final Logger LOGGER = Logger.getLogger(TaskScheduler.class.getName()); @@ -103,9 +103,16 @@ boolean checkIsTaskExecutable(CronTabList cronTabList){ void terminateMaintenanceTaskExecution(){ this.maintenanceQueue = new LinkedList<>(); - if(taskExecutor.isAlive()) + if(taskExecutor != null && taskExecutor.isAlive()) taskExecutor.interrupt(); LOGGER.log(Level.FINE,"Terminated Execution of maintenance tasks"); } + + List getMaintenanceQueue(){ + return maintenanceQueue; + } + Thread getTaskExecutor(){ + return taskExecutor; + } } diff --git a/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java b/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java index 69ccb780aa..d75f115315 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java @@ -3,21 +3,20 @@ import hudson.plugins.git.BranchSpec; import hudson.plugins.git.GitSCM; import hudson.plugins.git.extensions.GitSCMExtension; +import jenkins.model.Jenkins; import jenkins.plugins.git.GitSampleRepoRule; import jenkins.scm.api.SCMFileSystem; +import org.apache.commons.io.FileUtils; +import org.junit.After; import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.JenkinsRule; import java.io.File; +import java.io.IOException; import java.util.Collections; import java.util.List; -import java.util.concurrent.locks.Lock; -import static org.hamcrest.CoreMatchers.instanceOf; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; public class GitMaintenanceSCMTest { @@ -31,6 +30,15 @@ public class GitMaintenanceSCMTest { @Rule public JenkinsRule j = new JenkinsRule(); + @After + public void clearAllCaches() throws IOException { + File[] caches = new File(Jenkins.getInstanceOrNull().getRootDir(),"caches").listFiles(); + if(caches != null) + for(File cache : caches){ + FileUtils.deleteDirectory(cache); + } + } + @Test public void testGetCaches() throws Exception{ sampleRepo1.init(); @@ -63,13 +71,15 @@ public void testGetCaches() throws Exception{ assertTrue(cachesExists); } } -// + + // What happens to caches when deleted from jenkins controller. We need to delete the cache even from our HashSet present in AbstactGitSCM class // @Test // public void testNoCachesExistsOnJenkinsController(){ // List caches = GitMaintenanceSCM.getCaches(); +//// System.out.println(caches); // assertEquals(0,caches.size()); // } -// + // @Test // public void testGetLockAndCacheFile() throws Exception{ // sampleRepo1.init(); diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java index 4931cf315b..714d95a115 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java @@ -13,6 +13,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; @@ -71,7 +72,7 @@ public void testAddTasksToQueue() throws Exception { int length = 2; taskScheduler.addTasksToQueue(maintenanceTasks); - assertThat(taskScheduler.maintenanceQueue.size(),is(length)); + assertThat(taskScheduler.getMaintenanceQueue().size(),is(length)); } @Test @@ -95,7 +96,7 @@ public void testCreateNoExecutorThread() throws Exception{ List maintenanceTasks = config.getMaintenanceTasks(); taskScheduler.addTasksToQueue(maintenanceTasks); taskScheduler.createTaskExecutorThread(); - assertNull(taskScheduler.taskExecutor); + assertNull(taskScheduler.getTaskExecutor()); } @@ -108,7 +109,7 @@ public void testCreateExecutionThread() throws Exception{ List maintenanceTasks = config.getMaintenanceTasks(); taskScheduler.addTasksToQueue(maintenanceTasks); taskScheduler.createTaskExecutorThread(); - assertTrue(taskScheduler.taskExecutor.isAlive()); + assertTrue(taskScheduler.getTaskExecutor().isAlive()); } @Test @@ -144,4 +145,11 @@ public void testIncorrectCronSyntaxInput() throws ANTLRException{ } } + @Test + public void testTerminateMaintenanceTask(){ + taskScheduler.terminateMaintenanceTaskExecution(); + assertNull(taskScheduler.getTaskExecutor()); + assertEquals(0,taskScheduler.getMaintenanceQueue().size()); + } + } From cfca99cb56ac5c1ebc3f47e2bce2a53bdcce1651 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 7 Jul 2022 20:19:36 +0530 Subject: [PATCH 059/146] updated logic to not create caches by GitMaintenanceSCM --- .../jenkins/plugins/git/maintenance/GitMaintenanceSCM.java | 2 +- .../git/maintenance/MaintenanceTaskConfiguration.java | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java b/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java index 8007819009..b4398ff073 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java +++ b/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java @@ -56,7 +56,7 @@ public static List getCaches(){ List caches = new ArrayList<>(); for (String cacheEntry : getCacheEntries()) { - File cacheDir = getCacheDir(cacheEntry); + File cacheDir = getCacheDir(cacheEntry,false); Lock cacheLock = getCacheLock(cacheEntry); LOGGER.log(Level.FINE,"Cache Entry " + cacheEntry); caches.add(new Cache(cacheDir,cacheLock)); diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java index cda9eacdd0..3de4d01de5 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java @@ -97,10 +97,7 @@ static List getGitVersion(){ final TaskListener procListener = StreamTaskListener.fromStderr(); final ByteArrayOutputStream out = new ByteArrayOutputStream(); try { - int returnCode = new Launcher.LocalLauncher(procListener).launch().cmds("git", "--version").stdout(out).join(); - if (returnCode != 0) { - LOGGER.log(Level.WARNING, "Command 'git --version' returned " + returnCode); - } + new Launcher.LocalLauncher(procListener).launch().cmds("git", "--version").stdout(out).join(); } catch (IOException | InterruptedException ex) { LOGGER.log(Level.WARNING, "Exception checking git version " + ex); } From 536de071b9092f5347d5b1f3633db136136051a7 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Fri, 8 Jul 2022 13:37:11 +0530 Subject: [PATCH 060/146] updated logic to execute git maintenance legacy --- .../plugins/git/maintenance/TaskExecutor.java | 84 +++++++++++++------ 1 file changed, 57 insertions(+), 27 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index 01660ca434..9bcfb1d8ba 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -35,8 +35,8 @@ public void run() { LOGGER.log(Level.FINE,"Executing maintenance task " + maintenanceTask.getTaskName() + " on git caches."); GitClient gitClient; + TaskType taskType = maintenanceTask.getTaskType(); for(GitMaintenanceSCM.Cache cache : caches){ - // For now adding lock to all kinds of maintenance tasks. Need to study on which task needs a lock and which doesn't. Lock lock = cache.getLock(); File cacheFile = cache.getCacheFile(); @@ -45,16 +45,11 @@ public void run() { if(gitClient == null) return; - TaskType taskType = maintenanceTask.getTaskType(); - lock.lock(); LOGGER.log(Level.FINE,"Cache " + cacheFile.getName() + " locked."); - executeMaintenanceTask(gitClient,taskType); - - } catch (IOException | InterruptedException e) { - // What is this error??? - LOGGER.log(Level.WARNING,"Git Client couldn't be initialized."); + } catch (InterruptedException e) { + LOGGER.log(Level.FINE,"Couldn't run " + taskType.getTaskName() + ".Msg: " + e.getMessage()); }finally { lock.unlock(); LOGGER.log(Level.FINE,"Cache " + cacheFile.getName() + " unlocked."); @@ -89,11 +84,43 @@ void executeGitMaintenance(GitClient gitClient,TaskType taskType) throws Interru LOGGER.log(Level.WARNING,"Invalid maintenance task."); } } - void executeLegacyGitMaintenance(GitClient gitClient,TaskType taskType){ + void executeLegacyGitMaintenance(GitClient gitClient,TaskType taskType) throws InterruptedException{ LOGGER.log(Level.FINE,"Git version < 2.30.0 detected. Using legacy git maintenance commands"); + + // If git version < 2.18.0 =====> run only gc. + // If git version >= 2.18.0 && git version <=2.19.1 ======> run gc and commit-graph + // If git version >= 2.20.0 && git version < 2.30 ========> run gc , commit-graph && multi-pack-index + + if(gitVersionAtLeast(2,20,0)){ + // execute gc, commit-graph && multi-pack-index + if(taskType.equals(TaskType.GC)){ + gitClient.maintenanceLegacy("gc"); + }else if(taskType.equals(TaskType.INCREMENTAL_REPACK)){ + gitClient.maintenanceLegacy("incremental-repack"); + }else if(taskType.equals(TaskType.COMMIT_GRAPH)){ + gitClient.maintenanceLegacy("commit-graph"); + }else{ + LOGGER.log(Level.FINE,"Cannot execute " + taskType.getTaskName() + " maintenance task due to older git version"); + } + }else if(gitVersionAtLeast(2,18,0)){ + // execute gc && commit-graph + if(taskType.equals(TaskType.GC)) + gitClient.maintenanceLegacy("gc"); + else if(taskType.equals(TaskType.COMMIT_GRAPH)) + gitClient.maintenanceLegacy("commit-graph"); + else + LOGGER.log(Level.FINE,"Cannot execute " + taskType.getTaskName() + " maintenance task due to older git version"); + }else { + // These are git versions less than 2.18.0 + // execute gc only + if(taskType.equals(TaskType.GC)) + gitClient.maintenanceLegacy("gc"); + else + LOGGER.log(Level.FINE,"Cannot execute " + taskType.getTaskName() + " maintenance task due to older git version"); + } } - private boolean gitVersionAtLeast(int neededMajor, int neededMinor, int neededPatch){ + boolean gitVersionAtLeast(int neededMajor, int neededMinor, int neededPatch){ return MaintenanceTaskConfiguration.gitVersionAtLeast(neededMajor,neededMinor,neededPatch); } @@ -103,26 +130,29 @@ List getCaches(){ return caches; } - GitClient getGitClient(File file) throws IOException, InterruptedException { - // What exactly is default tool here? - TaskListener listener = new LogTaskListener(LOGGER,Level.FINE); - final Jenkins jenkins = Jenkins.getInstanceOrNull(); - // How to get Jenkins controller as the node? - GitTool gitTool = GitUtils.resolveGitTool(null,jenkins,null, listener); - if(gitTool == null) { - LOGGER.log(Level.WARNING,"No GitTool found while running " + maintenanceTask.getTaskName()); - return null; - } + GitClient getGitClient(File file){ + try { + TaskListener listener = new LogTaskListener(LOGGER, Level.FINE); + final Jenkins jenkins = Jenkins.getInstanceOrNull(); + // How to get Jenkins controller as the node? + GitTool gitTool = GitUtils.resolveGitTool(null, jenkins, null, listener); + if (gitTool == null) { + LOGGER.log(Level.WARNING, "No GitTool found while running " + maintenanceTask.getTaskName()); + return null; + } - String gitExe = gitTool.getGitExe(); - FilePath workspace = new FilePath(file); - Git git = Git.with(listener,null).in(workspace).using(gitExe); + String gitExe = gitTool.getGitExe(); + FilePath workspace = new FilePath(file); + Git git = Git.with(listener, null).in(workspace).using(gitExe); - GitClient gitClient = git.getClient(); - if(gitClient instanceof CliGitAPIImpl) - return gitClient; + GitClient gitClient = git.getClient(); + if (gitClient instanceof CliGitAPIImpl) + return gitClient; - LOGGER.log(Level.WARNING,"Cli Git is not being used to execute maintenance tasks"); + LOGGER.log(Level.WARNING, "Cli Git is not being used to execute maintenance tasks"); + }catch (InterruptedException | IOException e ){ + LOGGER.log(Level.WARNING,"Git Client couldn't be initialized."); + } return null; } } From 1b97858e7dca9ff51454e119e7d8c7d68e425b43 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Fri, 8 Jul 2022 13:41:23 +0530 Subject: [PATCH 061/146] added few tests TaskExecutor --- .../git/maintenance/TaskExecutorTest.java | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java index 2b55dd3d3d..1a2e9e1acb 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java @@ -1,13 +1,12 @@ package jenkins.plugins.git.maintenance; -import antlr.ANTLRException; import hudson.plugins.git.BranchSpec; import hudson.plugins.git.GitSCM; import jenkins.plugins.git.GitSampleRepoRule; import jenkins.scm.api.SCMFileSystem; import org.jenkinsci.plugins.gitclient.GitClient; -import org.junit.Before; -import org.junit.Rule; +import org.junit.BeforeClass; +import org.junit.ClassRule; import org.junit.Test; import org.jvnet.hudson.test.JenkinsRule; @@ -23,16 +22,16 @@ public class TaskExecutorTest { - @Rule - public JenkinsRule j = new JenkinsRule(); + @ClassRule + public static JenkinsRule j = new JenkinsRule(); - @Rule - public GitSampleRepoRule sampleRepo1 = new GitSampleRepoRule(); + @ClassRule + public static GitSampleRepoRule sampleRepo1 = new GitSampleRepoRule(); - TaskExecutor taskExecutor; + private static TaskExecutor taskExecutor; - @Before - public void setUp() throws Exception{ + @BeforeClass + public static void setUp() throws Exception{ // Tested for a single maintenance tasks. Do I have to test for all maintenance tasks? MaintenanceTaskConfiguration config = new MaintenanceTaskConfiguration(); config.setIsTaskConfigured(TaskType.COMMIT_GRAPH,true); @@ -59,13 +58,22 @@ public void testGitClient() throws IOException, InterruptedException { } @Test - public void testExecuteMaintenanceTask(){ - return; + public void testGitVersionAtLeast(){ + // This test is dependent on users machine. + taskExecutor.gitVersionAtLeast(2,1,1); } @Test - public void testRun(){ - return; + public void testGetCaches(){ + assertNotNull(taskExecutor.getCaches()); } + @Test + public void testExecuteMaintenanceTask() throws InterruptedException { + GitMaintenanceSCM.Cache cache = taskExecutor.getCaches().get(0); + File cacheFile = cache.getCacheFile(); + GitClient gitClient = taskExecutor.getGitClient(cacheFile); + TaskType taskType = TaskType.COMMIT_GRAPH; + taskExecutor.executeMaintenanceTask(gitClient,taskType); + } } From 70d547c1df6551cd4fdad19fbff6b9b2719604d5 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Sat, 9 Jul 2022 07:23:46 +0530 Subject: [PATCH 062/146] Added hash to CronTab --- .../jenkins/plugins/git/maintenance/TaskScheduler.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index 92f30c2741..5091de079f 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -3,6 +3,7 @@ import antlr.ANTLRException; import hudson.scheduler.CronTab; import hudson.scheduler.CronTabList; +import hudson.scheduler.Hash; import jenkins.model.GlobalConfiguration; import java.util.Calendar; @@ -10,6 +11,7 @@ import java.util.GregorianCalendar; import java.util.LinkedList; import java.util.List; +import java.util.Random; import java.util.logging.Level; import java.util.logging.Logger; @@ -88,7 +90,10 @@ boolean isGitMaintenanceTaskRunning(MaintenanceTaskConfiguration config){ } CronTabList getCronTabList(String cronSyntax) throws ANTLRException { - CronTab cronTab = new CronTab(cronSyntax.trim()); + Random random = new Random(); + // Random number between 0 & 100000 + String seed = String.valueOf((random.nextInt(100000))); + CronTab cronTab = new CronTab(cronSyntax.trim(), Hash.from(seed)); return new CronTabList(Collections.singletonList(cronTab)); } From 9b5655828812d3925e836aeb3582b76c3fc47b86 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Sun, 10 Jul 2022 15:45:00 +0530 Subject: [PATCH 063/146] added/updated tests --- .../git/maintenance/TaskScheduler.java | 1 + .../maintenance/GitMaintenanceSCMTest.java | 24 +++++++ .../MaintenanceTaskConfigurationTest.java | 25 +++---- .../ParameterizedCronSyntaxTest.java | 66 +++++++++++++++++++ .../git/maintenance/TaskSchedulerTest.java | 49 ++++---------- 5 files changed, 118 insertions(+), 47 deletions(-) create mode 100644 src/test/java/jenkins/plugins/git/maintenance/ParameterizedCronSyntaxTest.java diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index 5091de079f..231f971974 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -108,6 +108,7 @@ boolean checkIsTaskExecutable(CronTabList cronTabList){ void terminateMaintenanceTaskExecution(){ this.maintenanceQueue = new LinkedList<>(); + // A better mechanism to kill thread will be implemented. if(taskExecutor != null && taskExecutor.isAlive()) taskExecutor.interrupt(); diff --git a/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java b/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java index d75f115315..2c5cc67092 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java @@ -16,7 +16,12 @@ import java.io.IOException; import java.util.Collections; import java.util.List; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; public class GitMaintenanceSCMTest { @@ -64,6 +69,7 @@ public void testGetCaches() throws Exception{ boolean cachesExists = false; for(GitMaintenanceSCM gitMaintenanceSCM : gitMaintenanceSCMS){ cachesExists = gitMaintenanceSCM.getCacheEntryForTest().equals(cacheDir); + assertNull(gitMaintenanceSCM.getCredentialsId()); if(cachesExists) break; } @@ -96,4 +102,22 @@ public void testGetCaches() throws Exception{ // assertThat(cache.getCacheFile(),instanceOf(File.class)); // }); // } + + + @Test + public void testGetCacheFile(){ + File file = Jenkins.getInstanceOrNull().getRootDir(); + Lock lock = new ReentrantLock(); + GitMaintenanceSCM.Cache cache = new GitMaintenanceSCM.Cache(file,lock); + assertEquals(file.getAbsolutePath(),cache.getCacheFile().getAbsolutePath()); + } + + @Test + public void testGetLock(){ + File file = Jenkins.getInstanceOrNull().getRootDir(); + Lock lock = new ReentrantLock(); + GitMaintenanceSCM.Cache cache = new GitMaintenanceSCM.Cache(file,lock); + assertNotNull(cache.getLock()); + } + } diff --git a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java index c611ff0f5d..51b7b08934 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java @@ -15,16 +15,6 @@ public class MaintenanceTaskConfigurationTest { public static JenkinsRule j = new JenkinsRule(); private final MaintenanceTaskConfiguration config = new MaintenanceTaskConfiguration(); -// @Test -// public void configureMaintenanceTasks(){ -// config.configureMaintenanceTasks(); -// assertEquals(TaskType.GC,config.getMaintenanceTasks().get(TaskType.GC).task); -// assertEquals(TaskType.PREFETCH,config.getMaintenanceTasks().get(TaskType.PREFETCH).task); -// assertEquals(TaskType.INCREMENTAL_REPACK,config.getMaintenanceTasks().get(TaskType.INCREMENTAL_REPACK).task); -// assertEquals(TaskType.LOOSE_OBJECTS,config.getMaintenanceTasks().get(TaskType.LOOSE_OBJECTS).task); -// assertEquals(TaskType.COMMIT_GRAPH,config.getMaintenanceTasks().get(TaskType.COMMIT_GRAPH).task); -// } - @Test public void setCronSyntax() throws ANTLRException { String cronSyntax = "* * * 1 *"; @@ -76,7 +66,6 @@ public void setIsMaintenanceTaskRunning(){ @Test public void checkValidCronSyntax() throws ANTLRException { - // Doesn't throw any error MaintenanceTaskConfiguration.checkSanity("* * * * *"); MaintenanceTaskConfiguration.checkSanity("1 * * * * "); MaintenanceTaskConfiguration.checkSanity("H H(8-15)/2 * * 1-5"); @@ -90,4 +79,18 @@ public void checkInvalidCronSyntax() throws ANTLRException{ MaintenanceTaskConfiguration.checkSanity("a * * 1 *"); } + @Test + public void testGetGitVersion(){ + List gitVersion = MaintenanceTaskConfiguration.getGitVersion(); + assertEquals(3,gitVersion.size()); + } + + // This test depends on the computers git version. +// @Test +// public void testGitVersionAtLeast(){ +// assertTrue(MaintenanceTaskConfiguration.gitVersionAtLeast()); +// assertTrue(MaintenanceTaskConfiguration.gitVersionAtLeast()); +// assertTrue(MaintenanceTaskConfiguration.gitVersionAtLeast()); +// assertTrue(MaintenanceTaskConfiguration.gitVersionAtLeast()); +// } } diff --git a/src/test/java/jenkins/plugins/git/maintenance/ParameterizedCronSyntaxTest.java b/src/test/java/jenkins/plugins/git/maintenance/ParameterizedCronSyntaxTest.java new file mode 100644 index 0000000000..78d4455ff6 --- /dev/null +++ b/src/test/java/jenkins/plugins/git/maintenance/ParameterizedCronSyntaxTest.java @@ -0,0 +1,66 @@ +package jenkins.plugins.git.maintenance; + +import antlr.ANTLRException; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.jvnet.hudson.test.JenkinsRule; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +@RunWith(Parameterized.class) +public class ParameterizedCronSyntaxTest { + + @ClassRule + public static JenkinsRule j = new JenkinsRule(); + String cronSyntax; + boolean isValid; + + TaskScheduler taskScheduler; + + public ParameterizedCronSyntaxTest(String cronSyntax,boolean isValid){ + this.cronSyntax = cronSyntax; + this.isValid = isValid; + taskScheduler = new TaskScheduler(); + + } + + @Parameterized.Parameters(name = "{0}") + public static Collection permuteCronSyntax(){ + List crons = new ArrayList<>(); + // valid cron syntax + crons.add(new Object[]{"H * * * *",true}); + crons.add(new Object[]{"* * * * *", true}); + crons.add(new Object[]{"@hourly",true}); + crons.add(new Object[]{"@weekly",true}); + crons.add(new Object[]{"@daily",true}); + crons.add(new Object[]{"H H 1,15 1-11 *",true}); + + // invalid cron syntax; + crons.add(new Object[]{"",false}); + crons.add(new Object[]{"**", false}); + crons.add(new Object[]{"60 1 1 1 1",false}); + crons.add(new Object[]{"1 1 1 1 9",false}); + crons.add(new Object[]{"1 24 32 11 5",false}); + crons.add(new Object[]{"",false}); + return crons; + } + + @Test + public void testCorrectAndIncorrectSyntaxInput(){ + try { + assertNotNull(taskScheduler.getCronTabList(cronSyntax)); + assertTrue(isValid); + }catch(ANTLRException e){ + assertFalse(isValid); + } + } + +} diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java index 714d95a115..34d6f766ce 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java @@ -1,13 +1,11 @@ package jenkins.plugins.git.maintenance; import antlr.ANTLRException; -import hudson.scheduler.CronTabList; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.JenkinsRule; -import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -15,7 +13,6 @@ import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -112,39 +109,6 @@ public void testCreateExecutionThread() throws Exception{ assertTrue(taskScheduler.getTaskExecutor().isAlive()); } - @Test - public void testCorrectCronSyntaxInput() throws ANTLRException{ - List correctCronSyntax = new ArrayList<>(); - correctCronSyntax.add("H * * * *"); - correctCronSyntax.add("* * * * *"); - correctCronSyntax.add("@hourly"); - correctCronSyntax.add("@weekly"); - correctCronSyntax.add("@daily"); - correctCronSyntax.add("H H 1,15 1-11 *"); - - for(String cronSyntax : correctCronSyntax){ - CronTabList cronTabList = taskScheduler.getCronTabList(cronSyntax); - assertNotNull(cronTabList); - } - } - - @Test(expected = ANTLRException.class) - public void testIncorrectCronSyntaxInput() throws ANTLRException{ - List incorrectCronSyntax = new ArrayList<>(); - incorrectCronSyntax.add(""); - incorrectCronSyntax.add("**"); - - // Valid format is (0-59) (0–23) (1–31) (1–12) (0–7) - incorrectCronSyntax.add("60 1 1 1 1"); - incorrectCronSyntax.add("1 24 32 11 5"); - incorrectCronSyntax.add("1 1 1 1 9"); - - for(String cronSyntax : incorrectCronSyntax){ - // Should throw an exception. - taskScheduler.getCronTabList(cronSyntax); - } - } - @Test public void testTerminateMaintenanceTask(){ taskScheduler.terminateMaintenanceTaskExecution(); @@ -152,4 +116,17 @@ public void testTerminateMaintenanceTask(){ assertEquals(0,taskScheduler.getMaintenanceQueue().size()); } + @Test + public void testTerminateMaintenanceTaskDuringThreadExecution() throws InterruptedException { + config.setCronSyntax(TaskType.PREFETCH,"* * * * *"); + config.setIsTaskConfigured(TaskType.PREFETCH,true); + List tasks = config.getMaintenanceTasks(); + taskScheduler.addTasksToQueue(tasks); + taskScheduler.createTaskExecutorThread(); + + assertTrue(taskScheduler.getTaskExecutor().isAlive()); + taskScheduler.terminateMaintenanceTaskExecution(); + assertTrue(taskScheduler.getTaskExecutor().isInterrupted()); + } + } From 06e400a661c2abe640654dcdb6444fd01af94657 Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Tue, 12 Jul 2022 17:34:46 -0600 Subject: [PATCH 064/146] Use latest git client plugin --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0f67cc0c2c..b983ecde64 100644 --- a/pom.xml +++ b/pom.xml @@ -102,7 +102,7 @@ org.jenkins-ci.plugins git-client - 3.11.1-rc3079.e3ca_994f5da_a_ + 3.11.1-rc3100.a_658da_12c901 org.jenkins-ci.plugins From 3517854d1bf477aa839298a45efdd658c3c09782 Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Tue, 12 Jul 2022 17:41:09 -0600 Subject: [PATCH 065/146] Fix spotbugs warning for randomization in TaskScheduler --- .../java/jenkins/plugins/git/maintenance/TaskScheduler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index 231f971974..3729652bfa 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -23,6 +23,7 @@ public class TaskScheduler { private Thread taskExecutor; private static final Logger LOGGER = Logger.getLogger(TaskScheduler.class.getName()); + private static final Random random = new Random(); public TaskScheduler(){ this.config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); @@ -90,7 +91,6 @@ boolean isGitMaintenanceTaskRunning(MaintenanceTaskConfiguration config){ } CronTabList getCronTabList(String cronSyntax) throws ANTLRException { - Random random = new Random(); // Random number between 0 & 100000 String seed = String.valueOf((random.nextInt(100000))); CronTab cronTab = new CronTab(cronSyntax.trim(), Hash.from(seed)); From 46e2a9618f438b5fe9ecd23955ae39c19d2eddb5 Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Tue, 12 Jul 2022 17:47:43 -0600 Subject: [PATCH 066/146] Fix spots warning for random generator --- .../java/jenkins/plugins/git/maintenance/TaskScheduler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index 3729652bfa..ce4722d31f 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -23,7 +23,7 @@ public class TaskScheduler { private Thread taskExecutor; private static final Logger LOGGER = Logger.getLogger(TaskScheduler.class.getName()); - private static final Random random = new Random(); + private static final Random RANDOM = new Random(); public TaskScheduler(){ this.config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); @@ -92,7 +92,7 @@ boolean isGitMaintenanceTaskRunning(MaintenanceTaskConfiguration config){ CronTabList getCronTabList(String cronSyntax) throws ANTLRException { // Random number between 0 & 100000 - String seed = String.valueOf((random.nextInt(100000))); + String seed = String.valueOf((RANDOM.nextInt(100000))); CronTab cronTab = new CronTab(cronSyntax.trim(), Hash.from(seed)); return new CronTabList(Collections.singletonList(cronTab)); } From 81a84f255761408f8d23f2fc30f2f99598b92e99 Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Tue, 12 Jul 2022 18:02:58 -0600 Subject: [PATCH 067/146] Fix spotbugs warning for character set encoding --- .../git/maintenance/MaintenanceTaskConfiguration.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java index 3de4d01de5..cc145acbe1 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java @@ -12,6 +12,8 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashMap; @@ -101,7 +103,12 @@ static List getGitVersion(){ } catch (IOException | InterruptedException ex) { LOGGER.log(Level.WARNING, "Exception checking git version " + ex); } - final String versionOutput = out.toString().trim(); + String versionOutput = ""; + try { + versionOutput = out.toString(StandardCharsets.UTF_8.toString()).trim(); + } catch (UnsupportedEncodingException ue) { + LOGGER.log(Level.WARNING, "Unsupported encoding checking git version", ue); + } final String[] fields = versionOutput.split(" ")[2].replaceAll("msysgit.", "").replaceAll("windows.", "").split("\\."); // 0th index is Major Version. From e40ca2dcbdbcb83b7ffacff43032904fbd2fe4c3 Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Tue, 12 Jul 2022 18:35:44 -0600 Subject: [PATCH 068/146] Improve git version assertions --- .../MaintenanceTaskConfigurationTest.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java index 51b7b08934..f8a63a25f6 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java @@ -7,6 +7,12 @@ import java.util.List; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.both; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.number.OrderingComparison.greaterThan; +import static org.hamcrest.number.OrderingComparison.lessThan; import static org.junit.Assert.assertEquals; public class MaintenanceTaskConfigurationTest { @@ -82,7 +88,12 @@ public void checkInvalidCronSyntax() throws ANTLRException{ @Test public void testGetGitVersion(){ List gitVersion = MaintenanceTaskConfiguration.getGitVersion(); - assertEquals(3,gitVersion.size()); + assertThat("Version list size error", gitVersion.size(), is(greaterThan(1))); + assertThat("Major version out of range", gitVersion.get(0), is(both(greaterThan(0)).and(lessThan(99)))); + assertThat("Minor version out of range", gitVersion.get(1), is(both(greaterThan(0)).and(lessThan(99)))); + if (gitVersion.size() > 2) { + assertThat("Patch version out of range", gitVersion.get(2), is(both(greaterThan(0)).and(lessThan(99)))); + } } // This test depends on the computers git version. From 16fd1802f281bcdc5a6f4d4deee6d930f66aa920 Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Tue, 12 Jul 2022 18:43:24 -0600 Subject: [PATCH 069/146] Use hamcrest assertions for readability --- .../MaintenanceTaskConfigurationTest.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java index f8a63a25f6..bfcab5533e 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java @@ -13,7 +13,7 @@ import static org.hamcrest.Matchers.not; import static org.hamcrest.number.OrderingComparison.greaterThan; import static org.hamcrest.number.OrderingComparison.lessThan; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; public class MaintenanceTaskConfigurationTest { @@ -32,7 +32,7 @@ public void setCronSyntax() throws ANTLRException { List maintenanceTasks = config.getMaintenanceTasks(); for(Task task : maintenanceTasks){ if(task.getTaskType().equals(taskType)){ - assertEquals(cronSyntax,task.getCronSyntax()); + assertThat(task.getCronSyntax(), is(cronSyntax)); break; } } @@ -51,7 +51,7 @@ public void setIsMaintenanceTaskConfigured(){ List maintenanceTasks = config.getMaintenanceTasks(); for(Task task : maintenanceTasks){ if(task.getTaskType().equals(taskType)){ - assertEquals(isMaintenanceTaskConfigured,task.getIsTaskConfigured()); + assertThat(task.getIsTaskConfigured(), is(isMaintenanceTaskConfigured)); break; } } @@ -60,13 +60,12 @@ public void setIsMaintenanceTaskConfigured(){ @Test public void setIsMaintenanceTaskRunning(){ - // When status is false. - boolean status = config.getIsGitMaintenanceRunning(); - assertEquals(false,status); + // Default status + assertFalse(config.getIsGitMaintenanceRunning()); // When status is set to true -// status = config.setIsGitMaintenanceTaskRunning(); -// assertEquals(true,status); + // Maintenance needs to be running + // assertTrue(config.getIsGitMaintenanceRunning()); } @Test From 08cf2a4b5ae623abb50897b514699ec2b29cba82 Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Tue, 12 Jul 2022 18:54:27 -0600 Subject: [PATCH 070/146] Use random, not RANDOM for static final object See https://stackoverflow.com/questions/7259687/java-naming-convention-for-static-final-variables/18641425#18641425 The state of the object is being changed and methods are being called on the object --- .../java/jenkins/plugins/git/maintenance/TaskScheduler.java | 4 ++-- src/test/java/hudson/plugins/git/util/GitUtilsTest.java | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index ce4722d31f..3729652bfa 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -23,7 +23,7 @@ public class TaskScheduler { private Thread taskExecutor; private static final Logger LOGGER = Logger.getLogger(TaskScheduler.class.getName()); - private static final Random RANDOM = new Random(); + private static final Random random = new Random(); public TaskScheduler(){ this.config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); @@ -92,7 +92,7 @@ boolean isGitMaintenanceTaskRunning(MaintenanceTaskConfiguration config){ CronTabList getCronTabList(String cronSyntax) throws ANTLRException { // Random number between 0 & 100000 - String seed = String.valueOf((RANDOM.nextInt(100000))); + String seed = String.valueOf((random.nextInt(100000))); CronTab cronTab = new CronTab(cronSyntax.trim(), Hash.from(seed)); return new CronTabList(Collections.singletonList(cronTab)); } diff --git a/src/test/java/hudson/plugins/git/util/GitUtilsTest.java b/src/test/java/hudson/plugins/git/util/GitUtilsTest.java index a79dad41a8..54a0a08aa0 100644 --- a/src/test/java/hudson/plugins/git/util/GitUtilsTest.java +++ b/src/test/java/hudson/plugins/git/util/GitUtilsTest.java @@ -98,7 +98,7 @@ public class GitUtilsTest { private GitUtils gitUtils; private static GitClient gitClient; - private static final Random RANDOM = new Random(); + private static final Random random = new Random(); @BeforeClass public static void createSampleOriginRepo() throws Exception { @@ -120,14 +120,14 @@ public static void createSampleOriginRepo() throws Exception { priorBranchSpecList.add(new BranchSpec(OLDER_BRANCH_NAME)); originRepo.git("checkout", "master"); - originRepo.write(fileName, "This is the " + HEAD_TAG_NAME_0 + " README file " + RANDOM.nextInt()); + originRepo.write(fileName, "This is the " + HEAD_TAG_NAME_0 + " README file " + random.nextInt()); originRepo.git("add", fileName); originRepo.git("commit", "-m", "Adding " + fileName + " tagged " + HEAD_TAG_NAME_0, fileName); originRepo.git("tag", HEAD_TAG_NAME_0); headTag0Id = ObjectId.fromString(originRepo.head()); headTag0Revision = new Revision(headTag0Id); - originRepo.write(fileName, "This is the README file " + RANDOM.nextInt()); + originRepo.write(fileName, "This is the README file " + random.nextInt()); originRepo.git("add", fileName); originRepo.git("commit", "-m", "Adding " + fileName, fileName); originRepo.git("tag", HEAD_TAG_NAME_1); From 53411d5434237adb6a0d702ebdfbc272a2dbad21 Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Tue, 12 Jul 2022 22:12:02 -0600 Subject: [PATCH 071/146] Fix test that I broke earlier 2.0.0 is a valid git version --- .../git/maintenance/MaintenanceTaskConfigurationTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java index bfcab5533e..9fff47c211 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java @@ -89,9 +89,9 @@ public void testGetGitVersion(){ List gitVersion = MaintenanceTaskConfiguration.getGitVersion(); assertThat("Version list size error", gitVersion.size(), is(greaterThan(1))); assertThat("Major version out of range", gitVersion.get(0), is(both(greaterThan(0)).and(lessThan(99)))); - assertThat("Minor version out of range", gitVersion.get(1), is(both(greaterThan(0)).and(lessThan(99)))); + assertThat("Minor version out of range", gitVersion.get(1), is(both(greaterThan(-1)).and(lessThan(99)))); if (gitVersion.size() > 2) { - assertThat("Patch version out of range", gitVersion.get(2), is(both(greaterThan(0)).and(lessThan(99)))); + assertThat("Patch version out of range", gitVersion.get(2), is(both(greaterThan(-1)).and(lessThan(99)))); } } From 2254d1d79560dd2d157c41eae7a9b6a451f6524e Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Wed, 13 Jul 2022 06:05:57 -0600 Subject: [PATCH 072/146] Prevent NPE in test iteration of caches --- .../jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java b/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java index 2c5cc67092..b10953577e 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java @@ -65,6 +65,9 @@ public void testGetCaches() throws Exception{ List caches = GitMaintenanceSCM.getCaches(); for(GitMaintenanceSCM.Cache cache : caches){ + if (cache == null) { + continue; + } String cacheDir = cache.getCacheFile().getName(); boolean cachesExists = false; for(GitMaintenanceSCM gitMaintenanceSCM : gitMaintenanceSCMS){ From 4eb5db747e92dda5a2b1c2a0d161c3dc53d6293d Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Wed, 13 Jul 2022 06:23:48 -0600 Subject: [PATCH 073/146] Avoid NPE in task executor getClient() --- .../plugins/git/maintenance/TaskExecutor.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index 9bcfb1d8ba..06cb0e227f 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -142,14 +142,18 @@ GitClient getGitClient(File file){ } String gitExe = gitTool.getGitExe(); - FilePath workspace = new FilePath(file); - Git git = Git.with(listener, null).in(workspace).using(gitExe); - - GitClient gitClient = git.getClient(); - if (gitClient instanceof CliGitAPIImpl) - return gitClient; + if (file != null) { + FilePath workspace = new FilePath(file); + Git git = Git.with(listener, null).in(workspace).using(gitExe); + + GitClient gitClient = git.getClient(); + if (gitClient instanceof CliGitAPIImpl) + return gitClient; + LOGGER.log(Level.WARNING, "JGit requested, but does not execute maintenance tasks"); + } else { + LOGGER.log(Level.WARNING, "Cli Git will not execute maintenance tasks due to null file arg"); + } - LOGGER.log(Level.WARNING, "Cli Git is not being used to execute maintenance tasks"); }catch (InterruptedException | IOException e ){ LOGGER.log(Level.WARNING,"Git Client couldn't be initialized."); } From 24c8a8a67d2f5b9344cbbe1b187694457d593c7a Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Wed, 13 Jul 2022 19:44:24 +0530 Subject: [PATCH 074/146] Efficient way of terminating maintenance thread --- .../plugins/git/maintenance/TaskExecutor.java | 48 ++++++++++++------- .../git/maintenance/TaskScheduler.java | 7 +-- .../git/maintenance/TaskSchedulerTest.java | 23 ++++++++- 3 files changed, 56 insertions(+), 22 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index 06cb0e227f..f9ca8ad648 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -19,6 +19,7 @@ public class TaskExecutor implements Runnable { + private volatile boolean isThreadAlive; Task maintenanceTask; private List caches; @@ -27,6 +28,7 @@ public class TaskExecutor implements Runnable { public TaskExecutor(Task maintenanceTask){ this.maintenanceTask = new Task(maintenanceTask); caches = getCaches(); + isThreadAlive = true; LOGGER.log(Level.FINE,"New Thread created to execute " + maintenanceTask.getTaskName()); } @@ -36,24 +38,32 @@ public void run() { LOGGER.log(Level.FINE,"Executing maintenance task " + maintenanceTask.getTaskName() + " on git caches."); GitClient gitClient; TaskType taskType = maintenanceTask.getTaskType(); - for(GitMaintenanceSCM.Cache cache : caches){ - // For now adding lock to all kinds of maintenance tasks. Need to study on which task needs a lock and which doesn't. - Lock lock = cache.getLock(); - File cacheFile = cache.getCacheFile(); - try { - gitClient = getGitClient(cacheFile); - if(gitClient == null) - return; - - lock.lock(); - LOGGER.log(Level.FINE,"Cache " + cacheFile.getName() + " locked."); - executeMaintenanceTask(gitClient,taskType); - } catch (InterruptedException e) { - LOGGER.log(Level.FINE,"Couldn't run " + taskType.getTaskName() + ".Msg: " + e.getMessage()); - }finally { - lock.unlock(); - LOGGER.log(Level.FINE,"Cache " + cacheFile.getName() + " unlocked."); + try { + for (GitMaintenanceSCM.Cache cache : caches) { + if (isThreadAlive) { + // For now adding lock to all kinds of maintenance tasks. Need to study on which task needs a lock and which doesn't. + Lock lock = cache.getLock(); + File cacheFile = cache.getCacheFile(); + try { + gitClient = getGitClient(cacheFile); + if (gitClient == null) + return; + + lock.lock(); + LOGGER.log(Level.FINE, "Cache " + cacheFile.getName() + " locked."); + executeMaintenanceTask(gitClient, taskType); + } catch (InterruptedException e) { + LOGGER.log(Level.FINE, "Couldn't run " + taskType.getTaskName() + ".Msg: " + e.getMessage()); + } finally { + lock.unlock(); + LOGGER.log(Level.FINE, "Cache " + cacheFile.getName() + " unlocked."); + } + } else { + throw new InterruptedException("Maintenance thread has been interrupted. Terminating..."); + } } + }catch (InterruptedException e){ + LOGGER.log(Level.WARNING,"Interrupted Exception. Msg: " + e.getMessage()); } } @@ -159,4 +169,8 @@ GitClient getGitClient(File file){ } return null; } + + public void terminateThread(){ + isThreadAlive = false; + } } diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index 3729652bfa..60099e5fb9 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -21,6 +21,7 @@ public class TaskScheduler { private Calendar cal; private List maintenanceQueue; private Thread taskExecutor; + private TaskExecutor taskExecutorRunnable; private static final Logger LOGGER = Logger.getLogger(TaskScheduler.class.getName()); private static final Random random = new Random(); @@ -59,7 +60,8 @@ void createTaskExecutorThread(){ // Create a new thread and execute the tasks present in the queue; if(!maintenanceQueue.isEmpty() && (taskExecutor == null || !taskExecutor.isAlive())) { Task currentTask = maintenanceQueue.remove(0); - taskExecutor = new Thread(new TaskExecutor(currentTask), "maintenance-task-executor"); + taskExecutorRunnable = new TaskExecutor(currentTask); + taskExecutor = new Thread(taskExecutorRunnable, "maintenance-task-executor"); taskExecutor.start(); LOGGER.log(Level.FINE,"Thread [" + taskExecutor.getName() +"] created to execute " + currentTask.getTaskName() + " task."); } @@ -108,9 +110,8 @@ boolean checkIsTaskExecutable(CronTabList cronTabList){ void terminateMaintenanceTaskExecution(){ this.maintenanceQueue = new LinkedList<>(); - // A better mechanism to kill thread will be implemented. if(taskExecutor != null && taskExecutor.isAlive()) - taskExecutor.interrupt(); + taskExecutorRunnable.terminateThread(); LOGGER.log(Level.FINE,"Terminated Execution of maintenance tasks"); } diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java index 34d6f766ce..970b213b60 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java @@ -1,11 +1,16 @@ package jenkins.plugins.git.maintenance; import antlr.ANTLRException; +import hudson.plugins.git.BranchSpec; +import hudson.plugins.git.GitSCM; +import jenkins.plugins.git.GitSampleRepoRule; +import jenkins.scm.api.SCMFileSystem; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.JenkinsRule; +import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -21,6 +26,9 @@ public class TaskSchedulerTest { @Rule public JenkinsRule j = new JenkinsRule(); + @Rule + public GitSampleRepoRule sampleRepo1 = new GitSampleRepoRule(); + private TaskScheduler taskScheduler; private MaintenanceTaskConfiguration config; @@ -117,16 +125,27 @@ public void testTerminateMaintenanceTask(){ } @Test - public void testTerminateMaintenanceTaskDuringThreadExecution() throws InterruptedException { + public void testTerminateMaintenanceTaskDuringThreadExecution() throws Exception { config.setCronSyntax(TaskType.PREFETCH,"* * * * *"); config.setIsTaskConfigured(TaskType.PREFETCH,true); + // Need to add few caches to test if the Thread is being terminated... + + sampleRepo1.init(); + sampleRepo1.git("checkout", "-b", "bug/JENKINS-42817"); + sampleRepo1.write("file", "modified"); + sampleRepo1.git("commit", "--all", "--message=dev"); + + SCMFileSystem.of(j.createFreeStyleProject(), new GitSCM(GitSCM.createRepoList(sampleRepo1.toString(), null), Collections.singletonList(new BranchSpec("*/bug/JENKINS-42817")), null, null, Collections.emptyList())); + List tasks = config.getMaintenanceTasks(); taskScheduler.addTasksToQueue(tasks); taskScheduler.createTaskExecutorThread(); assertTrue(taskScheduler.getTaskExecutor().isAlive()); taskScheduler.terminateMaintenanceTaskExecution(); - assertTrue(taskScheduler.getTaskExecutor().isInterrupted()); + // This test could depend on CPU speed. Faster execution can fail the test. + Thread.sleep(1); + assertFalse(taskScheduler.getTaskExecutor().isAlive()); } } From a20c50ce06debe024d2591ac08858bb0f1e8b4ab Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 14 Jul 2022 17:30:18 +0530 Subject: [PATCH 075/146] removed assert syntax --- .../git/maintenance/MaintenanceUI.java | 72 +++++++++++-------- .../git/maintenance/TaskScheduler.java | 17 +++-- 2 files changed, 51 insertions(+), 38 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index 731e1ec04f..ac32ec2ba8 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -21,6 +21,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; @@ -66,19 +67,21 @@ public void doSave(StaplerRequest req, StaplerResponse res) throws IOException, JSONObject formData = req.getSubmittedForm(); MaintenanceTaskConfiguration config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); - // Need to check with mentors if I can use the below syntax. - assert config != null; - for (TaskType taskType : TaskType.values()) { - JSONObject maintenanceData = formData.getJSONObject(taskType.toString()); - String cronSyntax = maintenanceData.getString("cronSyntax"); - boolean isApplied = maintenanceData.getBoolean("isApplied"); + if(config != null) { + for (TaskType taskType : TaskType.values()) { + JSONObject maintenanceData = formData.getJSONObject(taskType.toString()); + String cronSyntax = maintenanceData.getString("cronSyntax"); + boolean isApplied = maintenanceData.getBoolean("isApplied"); - config.setCronSyntax(taskType, cronSyntax); - config.setIsTaskConfigured(taskType, isApplied); + config.setCronSyntax(taskType, cronSyntax); + config.setIsTaskConfigured(taskType, isApplied); + } + config.save(); + LOGGER.log(Level.FINE, "Maintenance configuration data stored successfully on Jenkins."); + res.sendRedirect(""); + return; } - config.save(); - LOGGER.log(Level.FINE,"Maintenance configuration data stored successfully on Jenkins."); - res.sendRedirect(""); + LOGGER.log(Level.WARNING,"Couldn't load Global git maintenance configuration. Internal Error."); } @RequirePOST @@ -92,21 +95,26 @@ public void doToggleExecutionState(StaplerRequest req, StaplerResponse res) thro MaintenanceTaskConfiguration config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); - // Need to check with mentors if I can use the below syntax. - assert config != null; - boolean updatedGitMaintenanceExecutionStatus = !config.getIsGitMaintenanceRunning(); - config.setIsGitMaintenanceRunning(updatedGitMaintenanceExecutionStatus); - config.save(); - if(updatedGitMaintenanceExecutionStatus) - LOGGER.log(Level.FINE,"Git Maintenance tasks are scheduled for execution."); - else { - Cron cron = PeriodicWork.all().get(Cron.class); - assert cron != null; - cron.terminateMaintenanceTaskExecution(); - cron.cancel(); - LOGGER.log(Level.FINE, "Terminated scheduling of Git Maintenance tasks."); + if(config != null) { + boolean updatedGitMaintenanceExecutionStatus = !config.getIsGitMaintenanceRunning(); + config.setIsGitMaintenanceRunning(updatedGitMaintenanceExecutionStatus); + config.save(); + if (updatedGitMaintenanceExecutionStatus) + LOGGER.log(Level.FINE, "Git Maintenance tasks are scheduled for execution."); + else { + Cron cron = PeriodicWork.all().get(Cron.class); + if (cron != null) { + cron.terminateMaintenanceTaskExecution(); + cron.cancel(); + LOGGER.log(Level.FINE, "Terminated scheduling of Git Maintenance tasks."); + } else { + LOGGER.log(Level.WARNING, "Couldn't Terminate Maintenance Task. Internal Error."); + } + } + res.sendRedirect(""); + return; } - res.sendRedirect(""); + LOGGER.log(Level.WARNING,"Couldn't load Global git maintenance configuration. Internal Error."); } @POST @@ -131,16 +139,18 @@ public FormValidation doCheckCronSyntax(@QueryParameter String cronSyntax) throw public List getMaintenanceTasks(){ // Can check if git version doesn't support a maintenance task and remove that maintenance task from the UI. MaintenanceTaskConfiguration config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); - // Need to check with mentors if I can use the below syntax. - assert config != null; - return config.getMaintenanceTasks(); + if(config != null) + return config.getMaintenanceTasks(); + LOGGER.log(Level.WARNING,"Couldn't load Global git maintenance configuration. Internal Error."); + return new ArrayList<>(); } public boolean getIsGitMaintenanceRunning(){ MaintenanceTaskConfiguration config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); - // Need to check with mentors if I can use the below syntax. - assert config != null; - return config.getIsGitMaintenanceRunning(); + if(config != null) + return config.getIsGitMaintenanceRunning(); + LOGGER.log(Level.WARNING,"Couldn't load Global git maintenance configuration. Internal Error."); + return false; } public String getGitVersion(){ diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index 60099e5fb9..a00baaa7d1 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -34,18 +34,21 @@ public TaskScheduler(){ } public void scheduleTasks() { - assert config != null; - - if(!isGitMaintenanceTaskRunning(config)) { - // Logs ever 1 min. Need to check performance impact. - LOGGER.log(Level.FINER,"Maintenance Task execution not configured in UI."); - return; - } + if(config != null) { + if (!isGitMaintenanceTaskRunning(config)) { + // Logs ever 1 min. Need to check performance impact. + LOGGER.log(Level.FINER, "Maintenance Task execution not configured in UI."); + return; + } List configuredTasks = config.getMaintenanceTasks(); addTasksToQueue(configuredTasks); // Option of Using the same thread for executing more maintenance task, or create a new thread the next minute and execute the maintenance task. createTaskExecutorThread(); + }else{ + LOGGER.log(Level.FINE,"Couldn't load Global git maintenance configuration. Internal Error."); + } + } boolean checkIsTaskInQueue(Task task){ From ba20351540500ed1898b0251109952d63410c65c Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 14 Jul 2022 17:31:05 +0530 Subject: [PATCH 076/146] fixed bug which adds invalid cache directory --- src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java index b8bf2510f9..7dd422a0ef 100644 --- a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java +++ b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java @@ -1278,8 +1278,9 @@ protected static File getCacheDir(String cacheEntry, boolean createDirectory) { if (!cacheDir.isDirectory()) { if (createDirectory) { boolean ok = cacheDir.mkdirs(); - cacheEntries.add(cacheEntry); - if (!ok) { + if(ok) { + cacheEntries.add(cacheEntry); + }else{ LOGGER.log(Level.WARNING, "Failed mkdirs of {0}", cacheDir); } } else { From 7574ac3ff7d853b1a7926ae019e602a6cd84d317 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 14 Jul 2022 22:13:05 +0530 Subject: [PATCH 077/146] terminate thread when executing invalid maintenance task --- .../plugins/git/maintenance/TaskExecutor.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index f9ca8ad648..07bb1266c8 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -92,6 +92,7 @@ void executeGitMaintenance(GitClient gitClient,TaskType taskType) throws Interru gitClient.maintenance("loose-objects"); }else{ LOGGER.log(Level.WARNING,"Invalid maintenance task."); + terminateThread(); } } void executeLegacyGitMaintenance(GitClient gitClient,TaskType taskType) throws InterruptedException{ @@ -111,6 +112,7 @@ void executeLegacyGitMaintenance(GitClient gitClient,TaskType taskType) throws I gitClient.maintenanceLegacy("commit-graph"); }else{ LOGGER.log(Level.FINE,"Cannot execute " + taskType.getTaskName() + " maintenance task due to older git version"); + terminateThread(); } }else if(gitVersionAtLeast(2,18,0)){ // execute gc && commit-graph @@ -118,15 +120,19 @@ void executeLegacyGitMaintenance(GitClient gitClient,TaskType taskType) throws I gitClient.maintenanceLegacy("gc"); else if(taskType.equals(TaskType.COMMIT_GRAPH)) gitClient.maintenanceLegacy("commit-graph"); - else - LOGGER.log(Level.FINE,"Cannot execute " + taskType.getTaskName() + " maintenance task due to older git version"); + else { + LOGGER.log(Level.FINE, "Cannot execute " + taskType.getTaskName() + " maintenance task due to older git version"); + terminateThread(); + } }else { // These are git versions less than 2.18.0 // execute gc only if(taskType.equals(TaskType.GC)) gitClient.maintenanceLegacy("gc"); - else - LOGGER.log(Level.FINE,"Cannot execute " + taskType.getTaskName() + " maintenance task due to older git version"); + else { + LOGGER.log(Level.FINE, "Cannot execute " + taskType.getTaskName() + " maintenance task due to older git version"); + terminateThread(); + } } } From 55fd7ee81ff809a7571c63c2536d90dd7dc56d67 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Fri, 29 Jul 2022 07:11:05 +0530 Subject: [PATCH 078/146] Added notifications in UI --- .../git/maintenance/MaintenanceUI.java | 79 +++++++++++++++---- .../git/maintenance/MaintenanceUI/index.jelly | 31 ++++++-- 2 files changed, 89 insertions(+), 21 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index ac32ec2ba8..000e8bf4c0 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -15,6 +15,7 @@ import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.bind.JavaScriptMethod; import org.kohsuke.stapler.interceptor.RequirePOST; import org.kohsuke.stapler.verb.POST; @@ -29,6 +30,10 @@ @Extension public class MaintenanceUI extends ManagementLink { + JSONObject notification = new JSONObject(); + String OK = "OK"; + String ERROR = "ERROR"; + private static final Logger LOGGER = Logger.getLogger(MaintenanceUI.class.getName()); @Override @@ -78,15 +83,17 @@ public void doSave(StaplerRequest req, StaplerResponse res) throws IOException, } config.save(); LOGGER.log(Level.FINE, "Maintenance configuration data stored successfully on Jenkins."); + setNotification("Data saved on Jenkins.",OK); res.sendRedirect(""); return; } LOGGER.log(Level.WARNING,"Couldn't load Global git maintenance configuration. Internal Error."); + setNotification("Internal Error! Data not saved.",ERROR); } @RequirePOST @Restricted(NoExternalUse.class) - public void doToggleExecutionState(StaplerRequest req, StaplerResponse res) throws IOException { + public void doExecuteMaintenanceTask(StaplerRequest req, StaplerResponse res) throws IOException { if (!Jenkins.get().hasPermission(Jenkins.ADMINISTER)) { LOGGER.log(Level.WARNING,"User doesn't have the required permission to access git-maintenance"); res.sendError(HttpServletResponse.SC_FORBIDDEN); @@ -94,27 +101,55 @@ public void doToggleExecutionState(StaplerRequest req, StaplerResponse res) thro } MaintenanceTaskConfiguration config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); + if(config != null) { + + // Todo + // schedule maintenance tasks only if all cron syntax are valid. + // else can't schedule maintenance tasks. + + boolean updatedGitMaintenanceExecutionStatus = true; + config.setIsGitMaintenanceRunning(updatedGitMaintenanceExecutionStatus); + config.save(); + LOGGER.log(Level.FINE, "Git Maintenance tasks are scheduled for execution."); + setNotification("Scheduled Maintenance Tasks.",OK); + }else{ + setNotification("Internal Error! Tasks not scheduled.",ERROR); + } + res.sendRedirect(""); + return; + } + + @RequirePOST + @Restricted(NoExternalUse.class) + public void doTerminateMaintenanceTask(StaplerRequest req, StaplerResponse res) throws IOException { + if (!Jenkins.get().hasPermission(Jenkins.ADMINISTER)) { + LOGGER.log(Level.WARNING,"User doesn't have the required permission to access git-maintenance"); + res.sendError(HttpServletResponse.SC_FORBIDDEN); + return; + } + + MaintenanceTaskConfiguration config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); if(config != null) { - boolean updatedGitMaintenanceExecutionStatus = !config.getIsGitMaintenanceRunning(); + boolean updatedGitMaintenanceExecutionStatus = false; config.setIsGitMaintenanceRunning(updatedGitMaintenanceExecutionStatus); config.save(); - if (updatedGitMaintenanceExecutionStatus) - LOGGER.log(Level.FINE, "Git Maintenance tasks are scheduled for execution."); - else { - Cron cron = PeriodicWork.all().get(Cron.class); - if (cron != null) { - cron.terminateMaintenanceTaskExecution(); - cron.cancel(); - LOGGER.log(Level.FINE, "Terminated scheduling of Git Maintenance tasks."); - } else { - LOGGER.log(Level.WARNING, "Couldn't Terminate Maintenance Task. Internal Error."); - } + + Cron cron = PeriodicWork.all().get(Cron.class); + if (cron != null) { + cron.terminateMaintenanceTaskExecution(); + cron.cancel(); + LOGGER.log(Level.FINE, "Terminated scheduling of Git Maintenance tasks."); + setNotification("Terminated Maintenance Tasks.",OK); + } else { + LOGGER.log(Level.WARNING, "Couldn't Terminate Maintenance Task. Internal Error."); + setNotification("Internal Error! Couldn't Terminate Tasks.",ERROR); } - res.sendRedirect(""); - return; + }else{ + setNotification("Internal Error! Couldn't Terminate Tasks.",ERROR); } - LOGGER.log(Level.WARNING,"Couldn't load Global git maintenance configuration. Internal Error."); + res.sendRedirect(""); + return; } @POST @@ -174,4 +209,16 @@ public String updateGitVersionHelperText(){ public Permission getRequiredPermission() { return Jenkins.ADMINISTER; } + + @JavaScriptMethod + public void setNotification(String notification, String type){ + this.notification.put("msg",notification); + this.notification.put("type",type); + } + + @JavaScriptMethod + public JSONObject getNotification(){ + return notification; + } + } diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly index 4085fe9100..9519e84a51 100644 --- a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly @@ -19,15 +19,36 @@ - - + + + - - + + + + - +
+ + + From f42d6643e4effe4091dcfd0c46f63392c2342157 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Wed, 3 Aug 2022 04:33:26 +0530 Subject: [PATCH 079/146] Skip caches when locked --- .../plugins/git/maintenance/TaskExecutor.java | 24 ++++++--- .../git/maintenance/TaskSchedulerTest.java | 51 +++++++++---------- 2 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index 07bb1266c8..1889fabe3f 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -40,17 +40,20 @@ public void run() { TaskType taskType = maintenanceTask.getTaskType(); try { for (GitMaintenanceSCM.Cache cache : caches) { - if (isThreadAlive) { - // For now adding lock to all kinds of maintenance tasks. Need to study on which task needs a lock and which doesn't. - Lock lock = cache.getLock(); - File cacheFile = cache.getCacheFile(); + // For now adding lock to all kinds of maintenance tasks. Need to study on which task needs a lock and which doesn't. + Lock lock = cache.getLock(); + File cacheFile = cache.getCacheFile(); + + // If lock is not available on the cache, skip maintenance on this cache. + if (isThreadAlive && lock.tryLock()) { + + LOGGER.log(Level.FINE, "Cache " + cacheFile.getName() + " locked."); + try { gitClient = getGitClient(cacheFile); if (gitClient == null) - return; + throw new InterruptedException("Git Client couldn't be instantiated"); - lock.lock(); - LOGGER.log(Level.FINE, "Cache " + cacheFile.getName() + " locked."); executeMaintenanceTask(gitClient, taskType); } catch (InterruptedException e) { LOGGER.log(Level.FINE, "Couldn't run " + taskType.getTaskName() + ".Msg: " + e.getMessage()); @@ -58,8 +61,13 @@ public void run() { lock.unlock(); LOGGER.log(Level.FINE, "Cache " + cacheFile.getName() + " unlocked."); } + } else { - throw new InterruptedException("Maintenance thread has been interrupted. Terminating..."); + + if(!isThreadAlive) + throw new InterruptedException("Maintenance thread has been interrupted. Terminating..."); + else + LOGGER.log(Level.FINE,"Cache is already locked. Can't run maintenance on cache " + cacheFile.getName()); } } }catch (InterruptedException e){ diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java index 970b213b60..991f831aca 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java @@ -1,16 +1,12 @@ package jenkins.plugins.git.maintenance; import antlr.ANTLRException; -import hudson.plugins.git.BranchSpec; -import hudson.plugins.git.GitSCM; import jenkins.plugins.git.GitSampleRepoRule; -import jenkins.scm.api.SCMFileSystem; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.JenkinsRule; -import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -124,28 +120,29 @@ public void testTerminateMaintenanceTask(){ assertEquals(0,taskScheduler.getMaintenanceQueue().size()); } - @Test - public void testTerminateMaintenanceTaskDuringThreadExecution() throws Exception { - config.setCronSyntax(TaskType.PREFETCH,"* * * * *"); - config.setIsTaskConfigured(TaskType.PREFETCH,true); - // Need to add few caches to test if the Thread is being terminated... - - sampleRepo1.init(); - sampleRepo1.git("checkout", "-b", "bug/JENKINS-42817"); - sampleRepo1.write("file", "modified"); - sampleRepo1.git("commit", "--all", "--message=dev"); - - SCMFileSystem.of(j.createFreeStyleProject(), new GitSCM(GitSCM.createRepoList(sampleRepo1.toString(), null), Collections.singletonList(new BranchSpec("*/bug/JENKINS-42817")), null, null, Collections.emptyList())); - - List tasks = config.getMaintenanceTasks(); - taskScheduler.addTasksToQueue(tasks); - taskScheduler.createTaskExecutorThread(); - - assertTrue(taskScheduler.getTaskExecutor().isAlive()); - taskScheduler.terminateMaintenanceTaskExecution(); - // This test could depend on CPU speed. Faster execution can fail the test. - Thread.sleep(1); - assertFalse(taskScheduler.getTaskExecutor().isAlive()); - } + // Need to revist this test +// @Test +// public void testTerminateMaintenanceTaskDuringThreadExecution() throws Exception { +// config.setCronSyntax(TaskType.PREFETCH,"* * * * *"); +// config.setIsTaskConfigured(TaskType.PREFETCH,true); +// // Need to add few caches to test if the Thread is being terminated... +// +// sampleRepo1.init(); +// sampleRepo1.git("checkout", "-b", "bug/JENKINS-42817"); +// sampleRepo1.write("file", "modified"); +// sampleRepo1.git("commit", "--all", "--message=dev"); +// +// SCMFileSystem.of(j.createFreeStyleProject(), new GitSCM(GitSCM.createRepoList(sampleRepo1.toString(), null), Collections.singletonList(new BranchSpec("*/bug/JENKINS-42817")), null, null, Collections.emptyList())); +// +// List tasks = config.getMaintenanceTasks(); +// taskScheduler.addTasksToQueue(tasks); +// taskScheduler.createTaskExecutorThread(); +// +// assertTrue(taskScheduler.getTaskExecutor().isAlive()); +// taskScheduler.terminateMaintenanceTaskExecution(); +// // This test could depend on CPU speed. Faster execution can fail the test. +// Thread.sleep(1); +// assertFalse(taskScheduler.getTaskExecutor().isAlive()); +// } } From 890a1d5d8e6178ff39459c2444f168e1b0285518 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Sat, 13 Aug 2022 23:39:13 +0530 Subject: [PATCH 080/146] Added more tests, fixed spotbug issue --- .../git/maintenance/MaintenanceUI.java | 3 +- .../MaintenanceTaskConfigurationTest.java | 6 +- .../git/maintenance/TaskExecutorTest.java | 94 ++++++++++++++++--- .../git/maintenance/TaskSchedulerTest.java | 27 ++++-- 4 files changed, 104 insertions(+), 26 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index 000e8bf4c0..528dd1beff 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -218,7 +218,8 @@ public void setNotification(String notification, String type){ @JavaScriptMethod public JSONObject getNotification(){ - return notification; + // creating a copy... + return JSONObject.fromObject(notification.toString()); } } diff --git a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java index 9fff47c211..c73fe864c6 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java @@ -10,10 +10,10 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.both; import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.not; import static org.hamcrest.number.OrderingComparison.greaterThan; import static org.hamcrest.number.OrderingComparison.lessThan; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; public class MaintenanceTaskConfigurationTest { @@ -22,7 +22,7 @@ public class MaintenanceTaskConfigurationTest { private final MaintenanceTaskConfiguration config = new MaintenanceTaskConfiguration(); @Test - public void setCronSyntax() throws ANTLRException { + public void setCronSyntax(){ String cronSyntax = "* * * 1 *"; for(TaskType taskType : TaskType.values()){ config.setCronSyntax(taskType,cronSyntax); @@ -63,6 +63,8 @@ public void setIsMaintenanceTaskRunning(){ // Default status assertFalse(config.getIsGitMaintenanceRunning()); + config.setIsGitMaintenanceRunning(true); + assertTrue(config.getIsGitMaintenanceRunning()); // When status is set to true // Maintenance needs to be running // assertTrue(config.getIsGitMaintenanceRunning()); diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java index 1a2e9e1acb..5c60975f58 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java @@ -2,16 +2,20 @@ import hudson.plugins.git.BranchSpec; import hudson.plugins.git.GitSCM; +import jenkins.model.GlobalConfiguration; import jenkins.plugins.git.GitSampleRepoRule; import jenkins.scm.api.SCMFileSystem; import org.jenkinsci.plugins.gitclient.GitClient; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; import org.jvnet.hudson.test.JenkinsRule; import java.io.File; -import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -19,7 +23,10 @@ import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +@RunWith(Parameterized.class) public class TaskExecutorTest { @ClassRule @@ -29,37 +36,64 @@ public class TaskExecutorTest { public static GitSampleRepoRule sampleRepo1 = new GitSampleRepoRule(); private static TaskExecutor taskExecutor; + private TaskType taskType; + + public TaskExecutorTest(TaskType taskType) { + MaintenanceTaskConfiguration config = new MaintenanceTaskConfiguration(); + config.setIsTaskConfigured(taskType, true); + config.setCronSyntax(taskType, "* * * * *"); + List tasks = config.getMaintenanceTasks().stream().filter(Task::getIsTaskConfigured).collect(Collectors.toList()); + Task configuredTask = tasks.get(0); + taskExecutor = new TaskExecutor(configuredTask); + this.taskType = taskType; + } @BeforeClass public static void setUp() throws Exception{ - // Tested for a single maintenance tasks. Do I have to test for all maintenance tasks? - MaintenanceTaskConfiguration config = new MaintenanceTaskConfiguration(); - config.setIsTaskConfigured(TaskType.COMMIT_GRAPH,true); - config.setCronSyntax(TaskType.COMMIT_GRAPH,"* * * * *"); - List tasks = config.getMaintenanceTasks().stream().filter(Task::getIsTaskConfigured).collect(Collectors.toList()); - Task configuredTask = tasks.get(0); - - taskExecutor = new TaskExecutor(configuredTask); sampleRepo1.init(); sampleRepo1.git("checkout", "-b", "bug/JENKINS-42817"); sampleRepo1.write("file", "modified"); sampleRepo1.git("commit", "--all", "--message=dev"); + + // Create caches on Jenkins controller. SCMFileSystem.of(j.createFreeStyleProject(), new GitSCM(GitSCM.createRepoList(sampleRepo1.toString(), null), Collections.singletonList(new BranchSpec("*/bug/JENKINS-42817")), null, null, Collections.emptyList())); + + } + @Parameterized.Parameters(name = "{0}") + public static Collection permuteMaintenanceTasks(){ + + List maintenanceTasks = new ArrayList<>(); + + maintenanceTasks.add(new Object[]{TaskType.PREFETCH}); + maintenanceTasks.add(new Object[]{TaskType.GC}); + maintenanceTasks.add(new Object[]{TaskType.LOOSE_OBJECTS}); + maintenanceTasks.add(new Object[]{TaskType.INCREMENTAL_REPACK}); + maintenanceTasks.add(new Object[]{TaskType.COMMIT_GRAPH}); + return maintenanceTasks; } @Test - public void testGitClient() throws IOException, InterruptedException { + public void testGitClient(){ // Get directory of a single cache. + System.out.println(taskExecutor.getCaches()); + assertTrue(taskExecutor.getCaches().size() > 0); GitMaintenanceSCM.Cache cache = taskExecutor.getCaches().get(0); File cacheFile = cache.getCacheFile(); + assertNotNull(taskExecutor.getGitClient(cacheFile)); assertThat(taskExecutor.getGitClient(cacheFile),instanceOf(GitClient.class)); } + @Test + public void testNullFileInGetGitClient() { + GitClient client = taskExecutor.getGitClient(null); + assertNull(client); + } + + // This test is dependent on users machine. @Test public void testGitVersionAtLeast(){ - // This test is dependent on users machine. taskExecutor.gitVersionAtLeast(2,1,1); } @@ -68,12 +102,42 @@ public void testGetCaches(){ assertNotNull(taskExecutor.getCaches()); } + + // Test doesn't returns any result @Test - public void testExecuteMaintenanceTask() throws InterruptedException { + public void testExecuteGitMaintenance() throws InterruptedException { GitMaintenanceSCM.Cache cache = taskExecutor.getCaches().get(0); File cacheFile = cache.getCacheFile(); - GitClient gitClient = taskExecutor.getGitClient(cacheFile); - TaskType taskType = TaskType.COMMIT_GRAPH; - taskExecutor.executeMaintenanceTask(gitClient,taskType); + GitClient client = taskExecutor.getGitClient(cacheFile); + taskExecutor.executeGitMaintenance(client,taskType); } + + // Test doesn't returns any result + @Test + public void testExecuteLegacyGitMaintenance() throws InterruptedException { + GitMaintenanceSCM.Cache cache = taskExecutor.getCaches().get(0); + File cacheFile = cache.getCacheFile(); + GitClient client = taskExecutor.getGitClient(cacheFile); + + taskExecutor.executeLegacyGitMaintenance(client,taskType); + } + + // Test doesn't returns any result + @Test + public void testRunnable() { + MaintenanceTaskConfiguration config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); + config.setIsGitMaintenanceRunning(true); + config.setCronSyntax(taskType,"* * * * *"); + config.setIsTaskConfigured(taskType,true); + + TaskScheduler scheduler = new TaskScheduler(); + scheduler.scheduleTasks(); + } + + // Todo Need a way to test termination of execution thread. + +// @Test +// public void testTerminateThread(){ +// +// } } diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java index 991f831aca..3ef483d49f 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java @@ -1,6 +1,6 @@ package jenkins.plugins.git.maintenance; -import antlr.ANTLRException; +import jenkins.model.GlobalConfiguration; import jenkins.plugins.git.GitSampleRepoRule; import org.junit.Before; import org.junit.Rule; @@ -31,18 +31,20 @@ public class TaskSchedulerTest { @Before public void setUp() throws Exception { taskScheduler = new TaskScheduler(); - config = new MaintenanceTaskConfiguration(); - + config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); } // Tested all the internal functions of this method @Test - public void testScheduleTasks() throws ANTLRException { + public void testScheduleTasks() { + config.setIsGitMaintenanceRunning(true); + config.setCronSyntax(TaskType.PREFETCH,"* * * * *"); + config.setIsTaskConfigured(TaskType.PREFETCH,true); taskScheduler.scheduleTasks(); } @Test - public void testCheckIsTaskInQueue() throws Exception { + public void testCheckIsTaskInQueue(){ config.setCronSyntax(TaskType.PREFETCH,"* * * * *"); config.setIsTaskConfigured(TaskType.PREFETCH,true); @@ -58,7 +60,7 @@ public void testCheckIsTaskInQueue() throws Exception { } @Test - public void testAddTasksToQueue() throws Exception { + public void testAddTasksToQueue() { // Adding Maintenance tasks configuration; config.setCronSyntax(TaskType.PREFETCH,"* * * * *"); config.setIsTaskConfigured(TaskType.PREFETCH,true); @@ -76,6 +78,15 @@ public void testAddTasksToQueue() throws Exception { assertThat(taskScheduler.getMaintenanceQueue().size(),is(length)); } + @Test + public void testInvalidAddTasksToQueue() { + config.setCronSyntax(TaskType.PREFETCH,"*****"); + config.setIsTaskConfigured(TaskType.PREFETCH,true); + List maintenanceTasks = config.getMaintenanceTasks(); + taskScheduler.addTasksToQueue(maintenanceTasks); + assertThat(taskScheduler.getMaintenanceQueue().size(),is(0)); + } + @Test public void testIsGitMaintenanceTaskRunning(){ // Setting value to true @@ -90,7 +101,7 @@ public void testIsGitMaintenanceTaskRunning(){ } @Test - public void testCreateNoExecutorThread() throws Exception{ + public void testCreateNoExecutorThread(){ config.setCronSyntax(TaskType.PREFETCH,"5 1 1 1 1"); config.setIsTaskConfigured(TaskType.PREFETCH,true); @@ -102,7 +113,7 @@ public void testCreateNoExecutorThread() throws Exception{ } @Test - public void testCreateExecutionThread() throws Exception{ + public void testCreateExecutionThread(){ config.setCronSyntax(TaskType.PREFETCH,"* * * * *"); config.setIsTaskConfigured(TaskType.PREFETCH,true); From b1f75af47b47705522694579282dfafa2637dfa4 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Mon, 15 Aug 2022 23:28:44 +0530 Subject: [PATCH 081/146] xml storage logic for maintenance tasks --- pom.xml | 7 ++ .../plugins/git/maintenance/Logs/Record.java | 52 +++++++++++++++ .../git/maintenance/Logs/RecordList.java | 23 +++++++ .../git/maintenance/Logs/XmlSerialize.java | 64 +++++++++++++++++++ 4 files changed, 146 insertions(+) create mode 100644 src/main/java/jenkins/plugins/git/maintenance/Logs/Record.java create mode 100644 src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java create mode 100644 src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java diff --git a/pom.xml b/pom.xml index b983ecde64..8b5d1e1bec 100644 --- a/pom.xml +++ b/pom.xml @@ -79,6 +79,7 @@ false + 5.13.1.202206130422-r Max Low @@ -144,6 +145,12 @@ mailer + + com.thoughtworks.xstream + xstream + 1.4.19 + + org.jenkins-ci.plugins junit diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/Record.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/Record.java new file mode 100644 index 0000000000..dd48235ad3 --- /dev/null +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/Record.java @@ -0,0 +1,52 @@ +package jenkins.plugins.git.maintenance.Logs; + +public class Record { + String repoName; + int repoSize; + String maintenanceType; + int prevExecution; + String executionStatus; + int executionTime; + + public Record(String repoName,int repoSize, String maintenanceType){ + this.repoName = repoName; + this.repoSize = repoSize; + this.maintenanceType = maintenanceType; + } + + public String getRepoName() { + return repoName; + } + + public int getRepoSize() { + return repoSize; + } + + public String getMaintenanceType() { + return maintenanceType; + } + + public int getPrevExecution() { + return prevExecution; + } + + public void setPrevExecution(int prevExecution) { + this.prevExecution = prevExecution; + } + + public String getExecutionStatus() { + return executionStatus; + } + + public void setExecutionStatus(String executionStatus) { + this.executionStatus = executionStatus; + } + + public int getExecutionTime() { + return executionTime; + } + + public void setExecutionTime(int executionTime) { + this.executionTime = executionTime; + } +} diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java new file mode 100644 index 0000000000..078848aedf --- /dev/null +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java @@ -0,0 +1,23 @@ +package jenkins.plugins.git.maintenance.Logs; + +import java.util.LinkedList; +import java.util.List; + +public class RecordList { + List maintenanceRecords; + + public RecordList(){ + maintenanceRecords = new LinkedList<>(); + } + + public List getMaintenanceRecords(){ + return maintenanceRecords; + } + + public void addRecord(Record record){ + maintenanceRecords.add(record); + } + + // Todo need a way to clean the recordsList. + +} diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java new file mode 100644 index 0000000000..9d69a29abf --- /dev/null +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java @@ -0,0 +1,64 @@ +package jenkins.plugins.git.maintenance.Logs; + +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.io.xml.DomDriver; +import com.thoughtworks.xstream.security.AnyTypePermission; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; + +public class XmlSerialize{ + + XStream xStream; + + // Need to set the exact required path for storing the maintenance file. + String maintenanceRecordsFile = "maintenanceRecords.xml"; + + public XmlSerialize(){ + this.xStream = new XStream(new DomDriver()); + // Need to change the Permission type. Todo need to read documentation and update security. + this.xStream.addPermission(AnyTypePermission.ANY); + } + + public RecordList fetchMaintenanceData(){ + try { + RecordList recordList; + if (!new File(maintenanceRecordsFile).exists()) { + recordList = new RecordList(); + } else { + byte[] parsedXmlByteArr = Files.readAllBytes(Paths.get(maintenanceRecordsFile)); + String parsedXmlString = new String(parsedXmlByteArr, StandardCharsets.UTF_8); + + recordList = (RecordList) xStream.fromXML(parsedXmlString); + } + + return recordList; + }catch (IOException e){ + // Handle exception... + } + + return null; + } + + public boolean addRecord(Record record){ + RecordList recordList = fetchMaintenanceData(); + + if(recordList != null){ + try { + + // Currently, loading the entire file into memory, appending the xml file and writing the xml file back into memory. + // Can improve by adding a BufferReader and appending the required record into required line no without loading the entire file into memory + recordList.addRecord(record); + String xmlData = xStream.toXML(recordList); + Files.write(Paths.get(maintenanceRecordsFile), xmlData.getBytes(StandardCharsets.UTF_8)); + return true; + }catch (IOException e){ + // Handle exception... + } + } + return false; + } +} From a0916a518af9eed2b7f6b480074c6ef3e9cbbe4d Mon Sep 17 00:00:00 2001 From: Hrushikesh Date: Tue, 16 Aug 2022 13:41:39 +0530 Subject: [PATCH 082/146] Removed jgit version. --- pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8b5d1e1bec..6f375b6045 100644 --- a/pom.xml +++ b/pom.xml @@ -79,7 +79,6 @@ false - 5.13.1.202206130422-r Max Low From 3137c98d2ac2fd33f0ed5f252baed88b0173c96d Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Tue, 16 Aug 2022 14:45:47 +0530 Subject: [PATCH 083/146] init table creation in UI --- pom.xml | 4 ++ .../git/maintenance/Logs/XmlSerialize.java | 7 ++- .../git/maintenance/MaintenanceUI.java | 7 +++ .../git/maintenance/MaintenanceUI/index.jelly | 49 +++++++++++++++++++ 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6f375b6045..4ec6e8b75e 100644 --- a/pom.xml +++ b/pom.xml @@ -149,6 +149,10 @@ xstream 1.4.19 + + io.jenkins.plugins + data-tables-api + org.jenkins-ci.plugins diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java index 9d69a29abf..6451730454 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java @@ -9,6 +9,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.List; public class XmlSerialize{ @@ -23,7 +24,7 @@ public XmlSerialize(){ this.xStream.addPermission(AnyTypePermission.ANY); } - public RecordList fetchMaintenanceData(){ + RecordList fetchMaintenanceData(){ try { RecordList recordList; if (!new File(maintenanceRecordsFile).exists()) { @@ -61,4 +62,8 @@ public boolean addRecord(Record record){ } return false; } + + public List getMaintenanceRecords(){ + return fetchMaintenanceData().getMaintenanceRecords(); + } } diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index 528dd1beff..8622d38cdd 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -9,6 +9,8 @@ import hudson.util.FormValidation; import jenkins.model.GlobalConfiguration; import jenkins.model.Jenkins; +import jenkins.plugins.git.maintenance.Logs.Record; +import jenkins.plugins.git.maintenance.Logs.XmlSerialize; import net.sf.json.JSONObject; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; @@ -222,4 +224,9 @@ public JSONObject getNotification(){ return JSONObject.fromObject(notification.toString()); } + public List getMaintenanceRecords(){ + // Currently on every refresh, parsing xml file from disk and then displaying it. + // Todo improve performance by creating an object which loads the data initially from xml file and UI consumes the data from this object. + return new XmlSerialize().getMaintenanceRecords(); + } } diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly index 9519e84a51..ad954a72d2 100644 --- a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly @@ -1,6 +1,7 @@ +
@@ -33,7 +34,55 @@
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
${%Repo Name}${%Repo Size}${%Task}${%Previous Execution}${%Status}${%Execution Time}
+ ${record.getRepoName()} + + ${record.getRepoSize()} + + ${record.getMaintenanceType()} + + ${record.getPrevExecution()} + + ${record.getExecutionTime()} +
+
+
+ +
From 1d4f766f63bc929b4b60059e4deb0133d20edbac Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 18 Aug 2022 02:53:12 +0530 Subject: [PATCH 086/146] fixed spotbug issue --- .../java/jenkins/plugins/git/maintenance/Logs/RecordList.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java index 078848aedf..fbfc6ed615 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java @@ -11,7 +11,7 @@ public RecordList(){ } public List getMaintenanceRecords(){ - return maintenanceRecords; + return new LinkedList<>(maintenanceRecords); } public void addRecord(Record record){ From 28c496fdfc674961b535b2456ffdcf1d066ac08a Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 18 Aug 2022 13:15:05 +0530 Subject: [PATCH 087/146] Refactor code --- .../plugins/git/maintenance/TaskExecutor.java | 77 +++++++++---------- 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index 9288fdacef..ad3e11d12c 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -42,45 +42,12 @@ public TaskExecutor(Task maintenanceTask){ public void run() { LOGGER.log(Level.FINE,"Executing maintenance task " + maintenanceTask.getTaskName() + " on git caches."); - GitClient gitClient; - TaskType taskType = maintenanceTask.getTaskType(); try { for (GitMaintenanceSCM.Cache cache : caches) { // For now adding lock to all kinds of maintenance tasks. Need to study on which task needs a lock and which doesn't. Lock lock = cache.getLock(); File cacheFile = cache.getCacheFile(); - long executionTime = 0; - boolean executionStatus = false; - - // If lock is not available on the cache, skip maintenance on this cache. - if (isThreadAlive && lock.tryLock()) { - - LOGGER.log(Level.FINE, "Cache " + cacheFile.getName() + " locked."); - - try { - gitClient = getGitClient(cacheFile); - if (gitClient == null) - throw new InterruptedException("Git Client couldn't be instantiated"); - - executionTime -= System.currentTimeMillis(); - executeMaintenanceTask(gitClient, taskType); - executionTime += System.currentTimeMillis(); - executionStatus = true; - } catch (InterruptedException e) { - LOGGER.log(Level.FINE, "Couldn't run " + taskType.getTaskName() + ".Msg: " + e.getMessage()); - } finally { - lock.unlock(); - LOGGER.log(Level.FINE, "Cache " + cacheFile.getName() + " unlocked."); - } - - } else { - if(!isThreadAlive) - throw new InterruptedException("Maintenance thread has been interrupted. Terminating..."); - else - LOGGER.log(Level.FINE,"Cache is already locked. Can't run maintenance on cache " + cacheFile.getName()); - } - - xmlSerialize.addRecord(createRecord(cacheFile,taskType,executionStatus,executionTime)); // Stores the record inside jenkins. + executeMaintenanceTask(cacheFile,lock); } }catch (InterruptedException e){ LOGGER.log(Level.WARNING,"Interrupted Exception. Msg: " + e.getMessage()); @@ -88,13 +55,45 @@ public void run() { } - void executeMaintenanceTask(GitClient gitClient,TaskType taskType) throws InterruptedException{ + void executeMaintenanceTask(File cacheFile,Lock lock) throws InterruptedException{ - if(gitVersionAtLeast(2,30,0)){ - executeGitMaintenance(gitClient,taskType); - }else{ - executeLegacyGitMaintenance(gitClient,taskType); + TaskType taskType = maintenanceTask.getTaskType(); + long executionTime = 0; + boolean executionStatus = false; + GitClient gitClient; + // If lock is not available on the cache, skip maintenance on this cache. + if (isThreadAlive && lock.tryLock()) { + + LOGGER.log(Level.FINE, "Cache " + cacheFile.getName() + " locked."); + + try { + gitClient = getGitClient(cacheFile); + if (gitClient == null) + throw new InterruptedException("Git Client couldn't be instantiated"); + + executionTime -= System.currentTimeMillis(); + if(gitVersionAtLeast(2,30,0)){ + executeGitMaintenance(gitClient,taskType); + }else{ + executeLegacyGitMaintenance(gitClient,taskType); + } + executionTime += System.currentTimeMillis(); + executionStatus = true; + } catch (InterruptedException e) { + LOGGER.log(Level.FINE, "Couldn't run " + taskType.getTaskName() + ".Msg: " + e.getMessage()); + } finally { + lock.unlock(); + LOGGER.log(Level.FINE, "Cache " + cacheFile.getName() + " unlocked."); + } + + } else { + if(!isThreadAlive) + throw new InterruptedException("Maintenance thread has been interrupted. Terminating..."); + else + LOGGER.log(Level.FINE,"Cache is already locked. Can't run maintenance on cache " + cacheFile.getName()); } + + xmlSerialize.addRecord(createRecord(cacheFile,taskType,executionStatus,executionTime)); // Stores the record inside jenkins. } void executeGitMaintenance(GitClient gitClient,TaskType taskType) throws InterruptedException { From 47534265e652a1f8b4be7286ebfa1c2eaf2e378d Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Fri, 19 Aug 2022 23:02:03 +0530 Subject: [PATCH 088/146] insert data to front of linked list --- .../java/jenkins/plugins/git/maintenance/Logs/RecordList.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java index fbfc6ed615..7b08d1c474 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java @@ -4,7 +4,7 @@ import java.util.List; public class RecordList { - List maintenanceRecords; + LinkedList maintenanceRecords; public RecordList(){ maintenanceRecords = new LinkedList<>(); @@ -15,7 +15,7 @@ public List getMaintenanceRecords(){ } public void addRecord(Record record){ - maintenanceRecords.add(record); + maintenanceRecords.addFirst(record); } // Todo need a way to clean the recordsList. From c201e0b706d698be61d23faf73b9e84562679ede Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 25 Aug 2022 21:02:06 +0530 Subject: [PATCH 089/146] store records based on caches --- .../git/maintenance/Logs/CacheRecord.java | 90 +++++++++++++++++++ .../plugins/git/maintenance/Logs/Record.java | 56 ------------ .../git/maintenance/Logs/RecordList.java | 40 +++++++-- .../git/maintenance/Logs/XmlSerialize.java | 6 +- .../git/maintenance/MaintenanceUI.java | 4 +- .../plugins/git/maintenance/TaskExecutor.java | 30 ++++--- 6 files changed, 144 insertions(+), 82 deletions(-) create mode 100644 src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java delete mode 100644 src/main/java/jenkins/plugins/git/maintenance/Logs/Record.java diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java new file mode 100644 index 0000000000..da120ced1c --- /dev/null +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java @@ -0,0 +1,90 @@ +package jenkins.plugins.git.maintenance.Logs; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.LinkedList; + +public class CacheRecord { + String repoName; + String repoSize; + String maintenanceType; + long timeOfExecution; + boolean executionStatus; + long executionDuration; + + LinkedList maintenanceData; + + + // This is to create a new Cache Record when cache is not present. + public CacheRecord(String repoName,String maintenanceType){ + this.repoName = repoName; + this.maintenanceType = maintenanceType; + maintenanceData = new LinkedList<>(); + maintenanceData.addFirst(this); + } + + // This is to add maintenance data to existing Cache Record + public CacheRecord(CacheRecord cacheRecord){ + setExecutionDuration(cacheRecord.getExecutionDuration()); + setExecutionStatus(cacheRecord.getExecutionStatus()); + setRepoSize(cacheRecord.getRepoSize()); + setTimeOfExecution(cacheRecord.timeOfExecution); + setMaintenanceType(cacheRecord.getMaintenanceType()); + } + + + public String getRepoName() { + return repoName; + } + + public String getRepoSize() { + return repoSize; + } + public void setRepoSize(String repoSize) { + this.repoSize = repoSize; + } + + public String getMaintenanceType() { + return maintenanceType; + } + + public void setMaintenanceType(String maintenanceType){ + this.maintenanceType = maintenanceType; + } + + public String getTimeOfExecution() { + Date date = new Date(timeOfExecution * 1000L); + SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm"); + return sdf.format(date); + } + + public void setTimeOfExecution(long timeOfExecution) { + this.timeOfExecution = timeOfExecution; + } + + public boolean getExecutionStatus() { + return executionStatus; + } + + public void setExecutionStatus(boolean executionStatus) { + this.executionStatus = executionStatus; + } + + public long getExecutionDuration() { + return executionDuration; + } + + public void setExecutionDuration(long executionDuration) { + this.executionDuration = executionDuration; + } + + public void insertMaintenanceData(CacheRecord record){ + if(record != null && maintenanceData != null) { + maintenanceData.addFirst(record); + + // Maximum storage of 5 Maintenance Records per Cache. + if(maintenanceData.size() > 5) + maintenanceData.removeLast(); + } + } +} diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/Record.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/Record.java deleted file mode 100644 index 7bfd16fd80..0000000000 --- a/src/main/java/jenkins/plugins/git/maintenance/Logs/Record.java +++ /dev/null @@ -1,56 +0,0 @@ -package jenkins.plugins.git.maintenance.Logs; - -public class Record { - String repoName; - long repoSize; - String maintenanceType; - int prevExecution; - boolean executionStatus; - long executionTime; - - // Can add space saved. - - public Record(String repoName,String maintenanceType){ - this.repoName = repoName; - this.maintenanceType = maintenanceType; - } - - public String getRepoName() { - return repoName; - } - - public long getRepoSize() { - return repoSize; - } - public void setRepoSize(long repoSize) { - this.repoSize = repoSize; - } - - public String getMaintenanceType() { - return maintenanceType; - } - - public int getPrevExecution() { - return prevExecution; - } - - public void setPrevExecution(int prevExecution) { - this.prevExecution = prevExecution; - } - - public boolean getExecutionStatus() { - return executionStatus; - } - - public void setExecutionStatus(boolean executionStatus) { - this.executionStatus = executionStatus; - } - - public long getExecutionTime() { - return executionTime; - } - - public void setExecutionTime(long executionTime) { - this.executionTime = executionTime; - } -} diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java index 7b08d1c474..a72843b9e9 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java @@ -1,23 +1,51 @@ package jenkins.plugins.git.maintenance.Logs; +import java.util.HashSet; +import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.Set; public class RecordList { - LinkedList maintenanceRecords; + LinkedList maintenanceRecords; + Set cacheSet; public RecordList(){ maintenanceRecords = new LinkedList<>(); + cacheSet = new HashSet<>(); } - public List getMaintenanceRecords(){ + public List getMaintenanceRecords(){ return new LinkedList<>(maintenanceRecords); } - public void addRecord(Record record){ - maintenanceRecords.addFirst(record); - } + public void addRecord(CacheRecord cacheRecord){ + String repoName = cacheRecord.getRepoName(); + if(cacheSet.contains(repoName)){ + // need to add cache to existing record + Iterator itr = maintenanceRecords.iterator(); + + CacheRecord record; + while(itr.hasNext()){ + record = itr.next(); + if(record.getRepoName().equals(repoName)){ + itr.remove(); + CacheRecord childCacheRecord = new CacheRecord(cacheRecord); + + record.insertMaintenanceData(childCacheRecord); - // Todo need a way to clean the recordsList. + // Adds the latest cache to the top of the list + maintenanceRecords.addFirst(record); + + break; + } + } + return; + } + + // Creates a new Cache Entry and adds the data. + maintenanceRecords.addFirst(cacheRecord); + cacheSet.add(repoName); + } } diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java index a27aafc60e..7b071c7966 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java @@ -45,14 +45,12 @@ RecordList fetchMaintenanceData(){ return null; } - public boolean addRecord(Record record){ + public boolean addMaintenanceRecord(CacheRecord record){ RecordList recordList = fetchMaintenanceData(); if(recordList != null){ try { - // Currently, loading the entire file into memory, appending the xml file and writing the xml file back into memory. - // Can improve by adding a BufferReader and appending the required record into required line no without loading the entire file into memory recordList.addRecord(record); String xmlData = xStream.toXML(recordList); Files.write(Paths.get(maintenanceRecordsFile), xmlData.getBytes(StandardCharsets.UTF_8)); @@ -64,7 +62,7 @@ public boolean addRecord(Record record){ return false; } - public List getMaintenanceRecords(){ + public List getMaintenanceRecords(){ return fetchMaintenanceData().getMaintenanceRecords(); } } diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index a3e9ff09d1..099bff6d35 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -9,7 +9,7 @@ import hudson.util.FormValidation; import jenkins.model.GlobalConfiguration; import jenkins.model.Jenkins; -import jenkins.plugins.git.maintenance.Logs.Record; +import jenkins.plugins.git.maintenance.Logs.CacheRecord; import jenkins.plugins.git.maintenance.Logs.XmlSerialize; import net.sf.json.JSONObject; import org.kohsuke.accmod.Restricted; @@ -224,7 +224,7 @@ public JSONObject getNotification(){ return JSONObject.fromObject(notification.toString()); } - public List getMaintenanceRecords(){ + public List getMaintenanceRecords(){ // Currently on every refresh, parsing xml file from disk and then displaying it. // Todo improve performance by creating an object which loads the data initially from xml file and UI consumes the data from this object. // Need to plan a way to load data async. Not the entire data. Based on user requirements. diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index ad3e11d12c..4de0f55bba 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -6,7 +6,7 @@ import hudson.plugins.git.util.GitUtils; import hudson.util.LogTaskListener; import jenkins.model.Jenkins; -import jenkins.plugins.git.maintenance.Logs.Record; +import jenkins.plugins.git.maintenance.Logs.CacheRecord; import jenkins.plugins.git.maintenance.Logs.XmlSerialize; import org.apache.commons.io.FileUtils; import org.jenkinsci.plugins.gitclient.CliGitAPIImpl; @@ -58,7 +58,7 @@ public void run() { void executeMaintenanceTask(File cacheFile,Lock lock) throws InterruptedException{ TaskType taskType = maintenanceTask.getTaskType(); - long executionTime = 0; + long executionDuration = 0; boolean executionStatus = false; GitClient gitClient; // If lock is not available on the cache, skip maintenance on this cache. @@ -71,13 +71,13 @@ void executeMaintenanceTask(File cacheFile,Lock lock) throws InterruptedExceptio if (gitClient == null) throw new InterruptedException("Git Client couldn't be instantiated"); - executionTime -= System.currentTimeMillis(); + executionDuration -= System.currentTimeMillis(); if(gitVersionAtLeast(2,30,0)){ executeGitMaintenance(gitClient,taskType); }else{ executeLegacyGitMaintenance(gitClient,taskType); } - executionTime += System.currentTimeMillis(); + executionDuration += System.currentTimeMillis(); executionStatus = true; } catch (InterruptedException e) { LOGGER.log(Level.FINE, "Couldn't run " + taskType.getTaskName() + ".Msg: " + e.getMessage()); @@ -93,7 +93,7 @@ void executeMaintenanceTask(File cacheFile,Lock lock) throws InterruptedExceptio LOGGER.log(Level.FINE,"Cache is already locked. Can't run maintenance on cache " + cacheFile.getName()); } - xmlSerialize.addRecord(createRecord(cacheFile,taskType,executionStatus,executionTime)); // Stores the record inside jenkins. + xmlSerialize.addMaintenanceRecord(createRecord(cacheFile,taskType,executionStatus,executionDuration)); // Stores the record in jenkins. } void executeGitMaintenance(GitClient gitClient,TaskType taskType) throws InterruptedException { @@ -199,15 +199,17 @@ public void terminateThread(){ isThreadAlive = false; } - Record createRecord(File cacheFile, TaskType taskType,boolean executionStatus,long executionTime){ - Record record = new Record(cacheFile.getName(),taskType.getTaskName()); - long repoSize = FileUtils.sizeOfDirectory(cacheFile); - record.setRepoSize(repoSize); - record.setExecutionStatus(executionStatus); + CacheRecord createRecord(File cacheFile, TaskType taskType,boolean executionStatus,long executionDuration){ + + CacheRecord cacheRecord = new CacheRecord(cacheFile.getName(),taskType.getTaskName()); + long repoSizeInBytes = FileUtils.sizeOfDirectory(cacheFile); + String repoSize = FileUtils.byteCountToDisplaySize(repoSizeInBytes); // Converts the bytes to KB,MB,GB + cacheRecord.setRepoSize(repoSize); + cacheRecord.setExecutionStatus(executionStatus); if(!executionStatus) - record.setExecutionTime(-1); - else record.setExecutionTime(executionTime); - record.setPrevExecution(12412); // Will update. Just testing. - return record; + cacheRecord.setExecutionDuration(-1); + else cacheRecord.setExecutionDuration(executionDuration); + cacheRecord.setTimeOfExecution(System.currentTimeMillis()/1000); // Store the unix timestamp + return cacheRecord; } } From 24729e300ee62c38de07050a7d9b34976c245ce8 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Thu, 25 Aug 2022 22:57:20 +0530 Subject: [PATCH 090/146] Added collapse and expand feature in table --- .../git/maintenance/Logs/CacheRecord.java | 6 ++ .../git/maintenance/Logs/RecordList.java | 16 ++++ .../git/maintenance/Logs/XmlSerialize.java | 4 + .../git/maintenance/MaintenanceUI.java | 23 +++++ .../git/maintenance/MaintenanceUI/table.jelly | 83 +++++++++++++++++-- 5 files changed, 123 insertions(+), 9 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java index da120ced1c..b8b7ad2c6a 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java @@ -3,6 +3,7 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.LinkedList; +import java.util.List; public class CacheRecord { String repoName; @@ -87,4 +88,9 @@ public void insertMaintenanceData(CacheRecord record){ maintenanceData.removeLast(); } } + + public List getAllMaintenanceRecordsForSingleCache(){ + return new LinkedList<>(maintenanceData); + } + } diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java index a72843b9e9..549e0d6e18 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java @@ -48,4 +48,20 @@ record = itr.next(); cacheSet.add(repoName); } + public List getAllMaintenanceRecordsForSingleCache(String cacheName) { + List allRecords = null; + + Iterator itr = maintenanceRecords.iterator(); + + CacheRecord record; + while(itr.hasNext()){ + record = itr.next(); + if(record.getRepoName().equals(cacheName)){ + allRecords = record.getAllMaintenanceRecordsForSingleCache(); + break; + } + } + + return allRecords; + } } diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java index 7b071c7966..960544019f 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java @@ -65,4 +65,8 @@ public boolean addMaintenanceRecord(CacheRecord record){ public List getMaintenanceRecords(){ return fetchMaintenanceData().getMaintenanceRecords(); } + + public List getAllMaintenanceRecordsForSingleCache(String cacheName) { + return fetchMaintenanceData().getAllMaintenanceRecordsForSingleCache(cacheName); + } } diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index 099bff6d35..f9444420f0 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -11,6 +11,7 @@ import jenkins.model.Jenkins; import jenkins.plugins.git.maintenance.Logs.CacheRecord; import jenkins.plugins.git.maintenance.Logs.XmlSerialize; +import net.sf.json.JSONArray; import net.sf.json.JSONObject; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; @@ -230,4 +231,26 @@ public List getMaintenanceRecords(){ // Need to plan a way to load data async. Not the entire data. Based on user requirements. return new XmlSerialize().getMaintenanceRecords(); } + + @JavaScriptMethod + public JSONObject getRecordsForSingleCache(String cacheName){ + List allMaintenanceRecordsOfCache = new XmlSerialize().getAllMaintenanceRecordsForSingleCache(cacheName); + JSONObject jsonObject = new JSONObject(); + JSONArray jsonArray = new JSONArray(); + + // Converting List of records to Json. + for(CacheRecord cacheRecord : allMaintenanceRecordsOfCache){ + JSONObject cacheObject = new JSONObject(); + cacheObject.put("maintenanceType",cacheRecord.getMaintenanceType()); + cacheObject.put("timeOfExecution",cacheRecord.getTimeOfExecution()); + cacheObject.put("executionStatus",cacheRecord.getExecutionStatus()); + cacheObject.put("executionDuration",cacheRecord.getExecutionDuration()); + cacheObject.put("repoSize",cacheRecord.getRepoSize()); + jsonArray.add(cacheObject); + } + + jsonObject.put("maintenanceData",jsonArray); + return jsonObject; + } + } diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/table.jelly b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/table.jelly index ca9320df8e..e99c5b37e6 100644 --- a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/table.jelly +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/table.jelly @@ -1,6 +1,5 @@ - +
@@ -11,9 +10,10 @@ ${%Repo Name} ${%Repo Size} ${%Task} - ${%Previous Execution} + ${%Time} ${%Status} - ${%Execution Time} + ${%Execution Time} (ms) + Expand @@ -29,17 +29,31 @@ ${record.getMaintenanceType()} - ${record.getPrevExecution()} + ${record.getTimeOfExecution()} ${record.getExecutionStatus()} - ${record.getExecutionTime()} + ${record.getExecutionDuration()} + + + Expand + + + + ${%Repo Name} + ${%Repo Size} + ${%Task} + ${%Previous Execution} + ${%Status} + ${%Execution Time} + +
@@ -47,9 +61,60 @@ From e16f547834faacdfb577bc26c3e84464e358828a Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Fri, 26 Aug 2022 02:21:06 +0530 Subject: [PATCH 091/146] Storing 5 records for each maintenance task --- .../git/maintenance/Logs/CacheRecord.java | 35 ++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java index b8b7ad2c6a..b8ac933b12 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java @@ -1,9 +1,15 @@ package jenkins.plugins.git.maintenance.Logs; +import jenkins.plugins.git.maintenance.TaskType; + import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; public class CacheRecord { String repoName; @@ -13,15 +19,20 @@ public class CacheRecord { boolean executionStatus; long executionDuration; - LinkedList maintenanceData; + Map> maintenanceData; // This is to create a new Cache Record when cache is not present. public CacheRecord(String repoName,String maintenanceType){ this.repoName = repoName; this.maintenanceType = maintenanceType; - maintenanceData = new LinkedList<>(); - maintenanceData.addFirst(this); + maintenanceData = new HashMap<>(); + + for(TaskType taskType : TaskType.values()){ + maintenanceData.put(taskType.getTaskName(),new LinkedList<>()); + } + + maintenanceData.get(maintenanceType).addFirst(this); } // This is to add maintenance data to existing Cache Record @@ -81,16 +92,24 @@ public void setExecutionDuration(long executionDuration) { public void insertMaintenanceData(CacheRecord record){ if(record != null && maintenanceData != null) { - maintenanceData.addFirst(record); - + LinkedList list = maintenanceData.get(record.getMaintenanceType()); + list.addFirst(record); // Maximum storage of 5 Maintenance Records per Cache. - if(maintenanceData.size() > 5) - maintenanceData.removeLast(); + if(list.size() > 5) + list.removeLast(); } } public List getAllMaintenanceRecordsForSingleCache(){ - return new LinkedList<>(maintenanceData); + List maintenanceData = new ArrayList<>(); + + for(Map.Entry> entry : this.maintenanceData.entrySet()){ + maintenanceData.addAll(entry.getValue()); + } + + Collections.sort(maintenanceData,(o1,o2) -> (int) (o2.timeOfExecution - o1.timeOfExecution)); + + return maintenanceData; } } From 4f6eba184db09f35aa32b21b59db1a64ca88c0ba Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Fri, 26 Aug 2022 03:04:34 +0530 Subject: [PATCH 092/146] fixed bug cronVerification due to calender --- .../java/jenkins/plugins/git/maintenance/TaskScheduler.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index a00baaa7d1..0ae22ab120 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -18,7 +18,6 @@ public class TaskScheduler { private MaintenanceTaskConfiguration config; - private Calendar cal; private List maintenanceQueue; private Thread taskExecutor; private TaskExecutor taskExecutorRunnable; @@ -28,7 +27,6 @@ public class TaskScheduler { public TaskScheduler(){ this.config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); - this.cal = new GregorianCalendar(); this.maintenanceQueue = new LinkedList(); LOGGER.log(Level.FINE,"TaskScheduler class Initialized."); } @@ -105,6 +103,7 @@ CronTabList getCronTabList(String cronSyntax) throws ANTLRException { boolean checkIsTaskExecutable(CronTabList cronTabList){ boolean isTaskExecutable = false; + Calendar cal = new GregorianCalendar(); isTaskExecutable = cronTabList.check(cal); // Further validation such as not schedule a task every minute etc. can be added here. From a8d9570fdcf973e3799cfde12700e118a34e9ad5 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Fri, 26 Aug 2022 03:16:15 +0530 Subject: [PATCH 093/146] update top most maintenance data for a cache --- .../jenkins/plugins/git/maintenance/Logs/RecordList.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java index 549e0d6e18..c96bd72129 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java @@ -34,6 +34,13 @@ record = itr.next(); record.insertMaintenanceData(childCacheRecord); + // Updates the Top most Cache with fresh data + record.setTimeOfExecution(childCacheRecord.timeOfExecution); + record.setExecutionStatus(childCacheRecord.getExecutionStatus()); + record.setRepoSize(childCacheRecord.getRepoSize()); + record.setMaintenanceType(childCacheRecord.getMaintenanceType()); + record.setExecutionDuration(childCacheRecord.executionDuration); + // Adds the latest cache to the top of the list maintenanceRecords.addFirst(record); From ed177e941340058575b5b492e0cdedef5b66d2df Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Fri, 26 Aug 2022 03:32:37 +0530 Subject: [PATCH 094/146] added serial no. to table --- .../git/maintenance/MaintenanceUI/table.jelly | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/table.jelly b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/table.jelly index e99c5b37e6..eaee76ad90 100644 --- a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/table.jelly +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/table.jelly @@ -7,6 +7,7 @@ + @@ -17,8 +18,11 @@ - + + @@ -68,31 +72,33 @@ // }); // function format(maintenanceRecords) { - let tableData = ""; + let tableData = ""; + let index = 1; + for(let record of maintenanceRecords){ + row = ''; + row+= '>' - for(let record of maintenanceRecords){ - row = ''; - for(let key in record){ - row+= '' + for(let key in record){ + row+= '' + } + row += ''; + tableData += row; } - row += ''; - tableData += row; - } - return ( - '
# ${%Repo Name} ${%Repo Size} ${%Task}
+ ${loop.count} + ${record.getRepoName()}
' + index++ + '
' + record[key] + '' + record[key] + '
' + - '' + - tableData + - '
TaskTimeStatusDuration (ms)RepoSize
' + return ( + '' + + '' + + tableData + + '
#TaskTimeStatusDuration (ms)RepoSize
' ); } jQuery(document).ready(function(){ var table = jQuery('#fixed').DataTable({ - pagingType: 'numbers', // Page number button only - }); + pagingType: 'numbers', // Page number button only, + }); jQuery('#fixed .expand').on('click',function(){ var tr = jQuery(this).closest('tr'); @@ -105,7 +111,7 @@ tr.find('svg').attr('data-icon', 'plus-circle'); // FontAwesome 5 } else { // Open this row - a.getRecordsForSingleCache(row.data()[0],function (t){ + a.getRecordsForSingleCache(row.data()[1],function (t){ var allMaintenanceRecords = t.responseObject()['maintenanceData']; // fetches all records when clicking expand button. row.child(format(allMaintenanceRecords)).show(); tr.addClass('shown'); From 39a5d6a6453f3e10bf46604d3587d8bec57d2f49 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Fri, 26 Aug 2022 04:11:51 +0530 Subject: [PATCH 095/146] remove unwanted code --- .../git/maintenance/MaintenanceUI/table.jelly | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/table.jelly b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/table.jelly index eaee76ad90..112b74530a 100644 --- a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/table.jelly +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/table.jelly @@ -64,13 +64,6 @@ From 89e02129a8c9840779bf63c9987a25958bbbde96 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Fri, 26 Aug 2022 04:39:13 +0530 Subject: [PATCH 096/146] fixed missing record in table --- .../plugins/git/maintenance/Logs/CacheRecord.java | 2 -- .../plugins/git/maintenance/Logs/RecordList.java | 10 ++++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java index b8ac933b12..bd8d157a4f 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java @@ -31,8 +31,6 @@ public CacheRecord(String repoName,String maintenanceType){ for(TaskType taskType : TaskType.values()){ maintenanceData.put(taskType.getTaskName(),new LinkedList<>()); } - - maintenanceData.get(maintenanceType).addFirst(this); } // This is to add maintenance data to existing Cache Record diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java index c96bd72129..8aea3e1454 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java @@ -29,7 +29,12 @@ public void addRecord(CacheRecord cacheRecord){ while(itr.hasNext()){ record = itr.next(); if(record.getRepoName().equals(repoName)){ - itr.remove(); + + // To not lose data of the first maintenance task + if(record.getAllMaintenanceRecordsForSingleCache().size() == 0){ + CacheRecord oldCacheRecord = new CacheRecord(record); + record.insertMaintenanceData(oldCacheRecord); + } CacheRecord childCacheRecord = new CacheRecord(cacheRecord); record.insertMaintenanceData(childCacheRecord); @@ -41,9 +46,6 @@ record = itr.next(); record.setMaintenanceType(childCacheRecord.getMaintenanceType()); record.setExecutionDuration(childCacheRecord.executionDuration); - // Adds the latest cache to the top of the list - maintenanceRecords.addFirst(record); - break; } } From 3e4a94e2ecd2c870981c99ac41998076de386189 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Fri, 26 Aug 2022 22:09:45 +0530 Subject: [PATCH 097/146] added xml file path --- .../plugins/git/maintenance/Logs/XmlSerialize.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java index 960544019f..e72e79a4b3 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java @@ -3,6 +3,7 @@ import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.xml.DomDriver; import com.thoughtworks.xstream.security.AnyTypePermission; +import jenkins.model.Jenkins; import java.io.File; import java.io.IOException; @@ -15,22 +16,23 @@ public class XmlSerialize{ XStream xStream; - // Need to set the exact required path for storing the maintenance file. - String maintenanceRecordsFile = "maintenanceRecords.xml"; + File maintenanceRecordsFile; public XmlSerialize(){ this.xStream = new XStream(new DomDriver()); // Need to change the Permission type. Todo need to read documentation and update security. this.xStream.addPermission(AnyTypePermission.ANY); + File rootDir = Jenkins.getInstanceOrNull().getRootDir(); + this.maintenanceRecordsFile = new File(rootDir.getAbsolutePath(),"maintenanceRecords.xml"); } RecordList fetchMaintenanceData(){ try { RecordList recordList; - if (!new File(maintenanceRecordsFile).exists()) { + if (!maintenanceRecordsFile.exists()) { recordList = new RecordList(); } else { - byte[] parsedXmlByteArr = Files.readAllBytes(Paths.get(maintenanceRecordsFile)); + byte[] parsedXmlByteArr = Files.readAllBytes(Paths.get(maintenanceRecordsFile.getAbsolutePath())); String parsedXmlString = new String(parsedXmlByteArr, StandardCharsets.UTF_8); xStream.setClassLoader(RecordList.class.getClassLoader()); @@ -53,7 +55,7 @@ public boolean addMaintenanceRecord(CacheRecord record){ recordList.addRecord(record); String xmlData = xStream.toXML(recordList); - Files.write(Paths.get(maintenanceRecordsFile), xmlData.getBytes(StandardCharsets.UTF_8)); + Files.write(Paths.get(maintenanceRecordsFile.getAbsolutePath()), xmlData.getBytes(StandardCharsets.UTF_8)); return true; }catch (IOException e){ // Handle exception... From 249e1e4456e3f798853e09ff29c6df9dae71d9c6 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Sat, 27 Aug 2022 03:14:58 +0530 Subject: [PATCH 098/146] Improve performance by reading data once from xml file --- .../git/maintenance/Logs/XmlSerialize.java | 48 ++++++++++++------- .../git/maintenance/MaintenanceUI.java | 3 -- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java index e72e79a4b3..083f755d59 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java @@ -18,33 +18,47 @@ public class XmlSerialize{ File maintenanceRecordsFile; + RecordList recordList; + public XmlSerialize(){ this.xStream = new XStream(new DomDriver()); // Need to change the Permission type. Todo need to read documentation and update security. this.xStream.addPermission(AnyTypePermission.ANY); - File rootDir = Jenkins.getInstanceOrNull().getRootDir(); - this.maintenanceRecordsFile = new File(rootDir.getAbsolutePath(),"maintenanceRecords.xml"); + Jenkins jenkins = Jenkins.getInstanceOrNull(); + + if(jenkins != null) { + File rootDir = jenkins.getRootDir(); + this.maintenanceRecordsFile = new File(rootDir.getAbsolutePath(), "maintenanceRecords.xml"); + } } RecordList fetchMaintenanceData(){ - try { - RecordList recordList; - if (!maintenanceRecordsFile.exists()) { - recordList = new RecordList(); - } else { - byte[] parsedXmlByteArr = Files.readAllBytes(Paths.get(maintenanceRecordsFile.getAbsolutePath())); - String parsedXmlString = new String(parsedXmlByteArr, StandardCharsets.UTF_8); - - xStream.setClassLoader(RecordList.class.getClassLoader()); - recordList = (RecordList) xStream.fromXML(parsedXmlString); - } + if(maintenanceRecordsFile == null){ + // Need to log..... + return null; + } - return recordList; - }catch (IOException e){ - // Handle exception... + // Checks if recordList is loaded from xml. If not loaded, load it. + if(recordList == null) { + + try { + RecordList recordList; + if (!maintenanceRecordsFile.exists()) { + recordList = new RecordList(); + } else { + byte[] parsedXmlByteArr = Files.readAllBytes(Paths.get(maintenanceRecordsFile.getAbsolutePath())); + String parsedXmlString = new String(parsedXmlByteArr, StandardCharsets.UTF_8); + + xStream.setClassLoader(RecordList.class.getClassLoader()); + recordList = (RecordList) xStream.fromXML(parsedXmlString); + } + this.recordList = recordList; + } catch (IOException e) { + // Handle exception... + } } - return null; + return this.recordList; } public boolean addMaintenanceRecord(CacheRecord record){ diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index f9444420f0..c6f5930738 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -226,9 +226,6 @@ public JSONObject getNotification(){ } public List getMaintenanceRecords(){ - // Currently on every refresh, parsing xml file from disk and then displaying it. - // Todo improve performance by creating an object which loads the data initially from xml file and UI consumes the data from this object. - // Need to plan a way to load data async. Not the entire data. Based on user requirements. return new XmlSerialize().getMaintenanceRecords(); } From da7a6bc9d149eaa54536973f36ed08f6806b219c Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Sat, 27 Aug 2022 03:31:56 +0530 Subject: [PATCH 099/146] Added logs to XmlSerialize.java --- .../git/maintenance/Logs/XmlSerialize.java | 16 ++++++++++++---- .../plugins/git/maintenance/MaintenanceUI.java | 2 -- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java index 083f755d59..acd22c3a72 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java @@ -4,6 +4,7 @@ import com.thoughtworks.xstream.io.xml.DomDriver; import com.thoughtworks.xstream.security.AnyTypePermission; import jenkins.model.Jenkins; +import jenkins.plugins.git.maintenance.GitMaintenanceSCM; import java.io.File; import java.io.IOException; @@ -11,6 +12,8 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; public class XmlSerialize{ @@ -20,6 +23,9 @@ public class XmlSerialize{ RecordList recordList; + String maintenanceFileName = "maintenanceRecords.xml"; + private static Logger LOGGER = Logger.getLogger(GitMaintenanceSCM.class.getName()); + public XmlSerialize(){ this.xStream = new XStream(new DomDriver()); // Need to change the Permission type. Todo need to read documentation and update security. @@ -28,33 +34,35 @@ public XmlSerialize(){ if(jenkins != null) { File rootDir = jenkins.getRootDir(); - this.maintenanceRecordsFile = new File(rootDir.getAbsolutePath(), "maintenanceRecords.xml"); + this.maintenanceRecordsFile = new File(rootDir.getAbsolutePath(), maintenanceFileName); } } RecordList fetchMaintenanceData(){ if(maintenanceRecordsFile == null){ // Need to log..... + LOGGER.log(Level.FINE,maintenanceFileName + " file path error."); return null; } // Checks if recordList is loaded from xml. If not loaded, load it. if(recordList == null) { - try { RecordList recordList; if (!maintenanceRecordsFile.exists()) { recordList = new RecordList(); + LOGGER.log(Level.FINE,maintenanceFileName + " file doesn't exist"); } else { byte[] parsedXmlByteArr = Files.readAllBytes(Paths.get(maintenanceRecordsFile.getAbsolutePath())); String parsedXmlString = new String(parsedXmlByteArr, StandardCharsets.UTF_8); xStream.setClassLoader(RecordList.class.getClassLoader()); recordList = (RecordList) xStream.fromXML(parsedXmlString); + LOGGER.log(Level.FINE,"Maintenance data loaded from " + maintenanceFileName); } this.recordList = recordList; } catch (IOException e) { - // Handle exception... + LOGGER.log(Level.FINE,"Couldn't load data from " + maintenanceFileName + ". Err: " + e.getMessage()); } } @@ -72,7 +80,7 @@ public boolean addMaintenanceRecord(CacheRecord record){ Files.write(Paths.get(maintenanceRecordsFile.getAbsolutePath()), xmlData.getBytes(StandardCharsets.UTF_8)); return true; }catch (IOException e){ - // Handle exception... + LOGGER.log(Level.FINE,"Error writing a record to " + maintenanceFileName + ". Err: " + e.getMessage()); } } return false; diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index c6f5930738..22d911f74f 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -120,7 +120,6 @@ public void doExecuteMaintenanceTask(StaplerRequest req, StaplerResponse res) th } res.sendRedirect(""); - return; } @RequirePOST @@ -152,7 +151,6 @@ public void doTerminateMaintenanceTask(StaplerRequest req, StaplerResponse res) setNotification("Internal Error! Couldn't Terminate Tasks.",ERROR); } res.sendRedirect(""); - return; } @POST From 6509ef9e5e931e5166a8f3fb0439ccd4f9ba20e8 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Sat, 27 Aug 2022 03:42:25 +0530 Subject: [PATCH 100/146] changed logging level added more logs --- .../plugins/git/maintenance/TaskExecutor.java | 13 +++++++------ .../plugins/git/maintenance/TaskScheduler.java | 8 ++++---- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index 4de0f55bba..9fd8ba357d 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -41,7 +41,7 @@ public TaskExecutor(Task maintenanceTask){ @Override public void run() { - LOGGER.log(Level.FINE,"Executing maintenance task " + maintenanceTask.getTaskName() + " on git caches."); + LOGGER.log(Level.INFO,"Executing maintenance task " + maintenanceTask.getTaskName() + " on git caches."); try { for (GitMaintenanceSCM.Cache cache : caches) { // For now adding lock to all kinds of maintenance tasks. Need to study on which task needs a lock and which doesn't. @@ -49,6 +49,8 @@ public void run() { File cacheFile = cache.getCacheFile(); executeMaintenanceTask(cacheFile,lock); } + + LOGGER.log(Level.INFO,maintenanceTask.getTaskName() + " has been executed successfully."); }catch (InterruptedException e){ LOGGER.log(Level.WARNING,"Interrupted Exception. Msg: " + e.getMessage()); } @@ -130,7 +132,7 @@ void executeLegacyGitMaintenance(GitClient gitClient,TaskType taskType) throws I }else if(taskType.equals(TaskType.COMMIT_GRAPH)){ gitClient.maintenanceLegacy("commit-graph"); }else{ - LOGGER.log(Level.FINE,"Cannot execute " + taskType.getTaskName() + " maintenance task due to older git version"); + LOGGER.log(Level.INFO,"Cannot execute " + taskType.getTaskName() + " maintenance task due to older git version"); terminateThread(); } }else if(gitVersionAtLeast(2,18,0)){ @@ -140,7 +142,7 @@ void executeLegacyGitMaintenance(GitClient gitClient,TaskType taskType) throws I else if(taskType.equals(TaskType.COMMIT_GRAPH)) gitClient.maintenanceLegacy("commit-graph"); else { - LOGGER.log(Level.FINE, "Cannot execute " + taskType.getTaskName() + " maintenance task due to older git version"); + LOGGER.log(Level.INFO, "Cannot execute " + taskType.getTaskName() + " maintenance task due to older git version"); terminateThread(); } }else { @@ -149,7 +151,7 @@ else if(taskType.equals(TaskType.COMMIT_GRAPH)) if(taskType.equals(TaskType.GC)) gitClient.maintenanceLegacy("gc"); else { - LOGGER.log(Level.FINE, "Cannot execute " + taskType.getTaskName() + " maintenance task due to older git version"); + LOGGER.log(Level.INFO, "Cannot execute " + taskType.getTaskName() + " maintenance task due to older git version"); terminateThread(); } } @@ -161,7 +163,7 @@ boolean gitVersionAtLeast(int neededMajor, int neededMinor, int neededPatch){ List getCaches(){ List caches = GitMaintenanceSCM.getCaches(); - LOGGER.log(Level.FINE,"Fetched all caches present on Jenkins Controller."); + LOGGER.log(Level.INFO,"Fetched all caches present on Jenkins Controller."); return caches; } @@ -169,7 +171,6 @@ GitClient getGitClient(File file){ try { TaskListener listener = new LogTaskListener(LOGGER, Level.FINE); final Jenkins jenkins = Jenkins.getInstanceOrNull(); - // How to get Jenkins controller as the node? GitTool gitTool = GitUtils.resolveGitTool(null, jenkins, null, listener); if (gitTool == null) { LOGGER.log(Level.WARNING, "No GitTool found while running " + maintenanceTask.getTaskName()); diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index 0ae22ab120..db562a31ef 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -27,7 +27,7 @@ public class TaskScheduler { public TaskScheduler(){ this.config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); - this.maintenanceQueue = new LinkedList(); + this.maintenanceQueue = new LinkedList<>(); LOGGER.log(Level.FINE,"TaskScheduler class Initialized."); } @@ -64,7 +64,7 @@ void createTaskExecutorThread(){ taskExecutorRunnable = new TaskExecutor(currentTask); taskExecutor = new Thread(taskExecutorRunnable, "maintenance-task-executor"); taskExecutor.start(); - LOGGER.log(Level.FINE,"Thread [" + taskExecutor.getName() +"] created to execute " + currentTask.getTaskName() + " task."); + LOGGER.log(Level.INFO,"Thread [" + taskExecutor.getName() +"] created to execute " + currentTask.getTaskName() + " task."); } } @@ -80,7 +80,7 @@ void addTasksToQueue(List configuredTasks){ isTaskExecutable = checkIsTaskExecutable(cronTabList); if(isTaskExecutable){ maintenanceQueue.add(task); - LOGGER.log(Level.FINE,task.getTaskName() + " added to maintenance queue."); + LOGGER.log(Level.INFO,task.getTaskName() + " added to maintenance queue."); } }catch (ANTLRException e){ // Logged every minute. Need to check performance. @@ -115,7 +115,7 @@ void terminateMaintenanceTaskExecution(){ if(taskExecutor != null && taskExecutor.isAlive()) taskExecutorRunnable.terminateThread(); - LOGGER.log(Level.FINE,"Terminated Execution of maintenance tasks"); + LOGGER.log(Level.INFO,"Terminated Execution of maintenance tasks"); } List getMaintenanceQueue(){ From 6061711b53957d96718ac6d328d686b010117a20 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Sat, 27 Aug 2022 04:51:52 +0530 Subject: [PATCH 101/146] added tests to CacheRecord --- .../git/maintenance/Logs/CacheRecord.java | 3 +- .../git/maintenance/Logs/CacheRecordTest.java | 136 ++++++++++++++++++ 2 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 src/test/java/jenkins/plugins/git/maintenance/Logs/CacheRecordTest.java diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java index bd8d157a4f..1f692e018d 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java @@ -10,6 +10,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Objects; public class CacheRecord { String repoName; @@ -89,7 +90,7 @@ public void setExecutionDuration(long executionDuration) { } public void insertMaintenanceData(CacheRecord record){ - if(record != null && maintenanceData != null) { + if(record != null && maintenanceData != null && this.repoName.equals(record.getRepoName())) { LinkedList list = maintenanceData.get(record.getMaintenanceType()); list.addFirst(record); // Maximum storage of 5 Maintenance Records per Cache. diff --git a/src/test/java/jenkins/plugins/git/maintenance/Logs/CacheRecordTest.java b/src/test/java/jenkins/plugins/git/maintenance/Logs/CacheRecordTest.java new file mode 100644 index 0000000000..2be77dd818 --- /dev/null +++ b/src/test/java/jenkins/plugins/git/maintenance/Logs/CacheRecordTest.java @@ -0,0 +1,136 @@ +package jenkins.plugins.git.maintenance.Logs; + +import jenkins.plugins.git.maintenance.TaskType; +import org.junit.Before; +import org.junit.Test; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.*; + +public class CacheRecordTest { + + CacheRecord record; + + @Before + public void setUp() throws Exception { + record = new CacheRecord("git-plugin", TaskType.GC.getTaskName()); + } + + @Test + public void testGetRepoName(){ + assertEquals("git-plugin",record.getRepoName()); + } + + @Test + public void testSetRepoSize(){ + record.setRepoSize("5MB"); + assertEquals(record.getRepoSize(),"5MB"); + } + + @Test + public void testSetMaintenanceType(){ + assertEquals(record.getMaintenanceType(),TaskType.GC.getTaskName()); + + record.setMaintenanceType(TaskType.PREFETCH.getTaskName()); + assertEquals(record.getMaintenanceType(),TaskType.PREFETCH.getTaskName()); + } + + @Test + public void testSetTimeOfExecution(){ + record.setTimeOfExecution(1661552520); + assertEquals(record.getTimeOfExecution(),"27-08-2022 03:52"); + } + + @Test + public void testSetExecutionStatus(){ + record.setExecutionStatus(false); + assertFalse(record.getExecutionStatus()); + + record.setExecutionStatus(true); + assertTrue(record.getExecutionStatus()); + } + + @Test + public void testSetExecutionDuration(){ + long duration = System.currentTimeMillis(); + record.setExecutionDuration(duration); + assertEquals(record.getExecutionDuration(),duration); + } + + @Test + public void testInsertMaintenanceData(){ + // Can add other metadata to these caches. + CacheRecord gcCacheRecord = new CacheRecord("git-plugin",TaskType.GC.getTaskName()); + CacheRecord prefetchRecord = new CacheRecord("git-plugin",TaskType.PREFETCH.getTaskName()); + CacheRecord commitGraphRecord = new CacheRecord("git-plugin",TaskType.COMMIT_GRAPH.getTaskName()); + CacheRecord incrementalRepackRecord = new CacheRecord("git-plugin",TaskType.INCREMENTAL_REPACK.getTaskName()); + CacheRecord looseObjectsRecord = new CacheRecord("git-plugin",TaskType.LOOSE_OBJECTS.getTaskName()); + + record.insertMaintenanceData(gcCacheRecord); + record.insertMaintenanceData(prefetchRecord); + record.insertMaintenanceData(commitGraphRecord); + record.insertMaintenanceData(incrementalRepackRecord); + record.insertMaintenanceData(looseObjectsRecord); + + for(Map.Entry> entry : record.maintenanceData.entrySet()){ + assertEquals(entry.getValue().size(),1); + } + } + + @Test + public void getAllMaintenanceRecordsForSingleCache(){ + CacheRecord gcCacheRecord = new CacheRecord("git-plugin",TaskType.GC.getTaskName()); + CacheRecord prefetchRecord = new CacheRecord("git-plugin",TaskType.PREFETCH.getTaskName()); + CacheRecord commitGraphRecord = new CacheRecord("git-plugin",TaskType.COMMIT_GRAPH.getTaskName()); + CacheRecord incrementalRepackRecord = new CacheRecord("git-plugin",TaskType.INCREMENTAL_REPACK.getTaskName()); + CacheRecord looseObjectsRecord = new CacheRecord("git-plugin",TaskType.LOOSE_OBJECTS.getTaskName()); + + // set the TimeofExecution for each cache + gcCacheRecord.setTimeOfExecution(1661552520); + prefetchRecord.setTimeOfExecution(1661553520); + commitGraphRecord.setTimeOfExecution(1661552120); + incrementalRepackRecord.setTimeOfExecution(1661572520); + looseObjectsRecord.setTimeOfExecution(1661512520); + + record.insertMaintenanceData(gcCacheRecord); + record.insertMaintenanceData(prefetchRecord); + record.insertMaintenanceData(commitGraphRecord); + record.insertMaintenanceData(incrementalRepackRecord); + record.insertMaintenanceData(looseObjectsRecord); + + // checking if the data received is in sorted manner or not. + boolean isSorted = true; + + List cacheRecords = record.getAllMaintenanceRecordsForSingleCache(); + + for(int i=1;i cacheRecords.get(i-1).timeOfExecution) { + isSorted = false; + } + } + + assertTrue(isSorted); + } + + @Test + public void copyCacheRecord(){ + long duration = System.currentTimeMillis(); + record.setExecutionDuration(duration); + record.setExecutionStatus(true); + record.setTimeOfExecution(1661552520); + record.setRepoSize("5MB"); + CacheRecord copyCacheRecord = new CacheRecord(record); + + assertEquals(copyCacheRecord.getExecutionDuration(),duration); + assertTrue(record.getExecutionStatus()); + assertEquals(copyCacheRecord.getTimeOfExecution(),"27-08-2022 03:52"); + assertEquals(copyCacheRecord.getMaintenanceType(),TaskType.GC.getTaskName()); + assertEquals(copyCacheRecord.getRepoSize(),"5MB"); + } + + + +} From 1d7e0942fa9d627c5179cda38c57c3ed58fe68b0 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Sat, 27 Aug 2022 14:09:25 +0530 Subject: [PATCH 102/146] fixed failing test --- .../git/maintenance/Logs/CacheRecordTest.java | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/test/java/jenkins/plugins/git/maintenance/Logs/CacheRecordTest.java b/src/test/java/jenkins/plugins/git/maintenance/Logs/CacheRecordTest.java index 2be77dd818..5afb1036a9 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/Logs/CacheRecordTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/Logs/CacheRecordTest.java @@ -4,6 +4,8 @@ import org.junit.Before; import org.junit.Test; +import java.text.SimpleDateFormat; +import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -40,8 +42,12 @@ public void testSetMaintenanceType(){ @Test public void testSetTimeOfExecution(){ - record.setTimeOfExecution(1661552520); - assertEquals(record.getTimeOfExecution(),"27-08-2022 03:52"); + long timeOfExecution = 1661552520; + record.setTimeOfExecution(timeOfExecution); + + Date date = new Date(timeOfExecution * 1000L); + SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm"); + assertEquals(record.getTimeOfExecution(),sdf.format(date)); } @Test @@ -109,6 +115,7 @@ public void getAllMaintenanceRecordsForSingleCache(){ for(int i=1;i cacheRecords.get(i-1).timeOfExecution) { isSorted = false; + break; } } @@ -118,17 +125,23 @@ public void getAllMaintenanceRecordsForSingleCache(){ @Test public void copyCacheRecord(){ long duration = System.currentTimeMillis(); + long timeOfExecution = 1661552520; + record.setExecutionDuration(duration); record.setExecutionStatus(true); - record.setTimeOfExecution(1661552520); + record.setTimeOfExecution(timeOfExecution); record.setRepoSize("5MB"); CacheRecord copyCacheRecord = new CacheRecord(record); assertEquals(copyCacheRecord.getExecutionDuration(),duration); assertTrue(record.getExecutionStatus()); - assertEquals(copyCacheRecord.getTimeOfExecution(),"27-08-2022 03:52"); assertEquals(copyCacheRecord.getMaintenanceType(),TaskType.GC.getTaskName()); assertEquals(copyCacheRecord.getRepoSize(),"5MB"); + + + Date date = new Date(timeOfExecution * 1000L); + SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm"); + assertEquals(copyCacheRecord.getTimeOfExecution(),sdf.format(date)); } From 4954fdfa7f85e3935bdf16192e2401a931d01f4d Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Sat, 27 Aug 2022 14:26:19 +0530 Subject: [PATCH 103/146] changed incorret order of assertEquals --- .../git/maintenance/Logs/CacheRecordTest.java | 19 +++++----- .../git/maintenance/Logs/RecordListTest.java | 35 +++++++++++++++++++ 2 files changed, 44 insertions(+), 10 deletions(-) create mode 100644 src/test/java/jenkins/plugins/git/maintenance/Logs/RecordListTest.java diff --git a/src/test/java/jenkins/plugins/git/maintenance/Logs/CacheRecordTest.java b/src/test/java/jenkins/plugins/git/maintenance/Logs/CacheRecordTest.java index 5afb1036a9..40980b23e4 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/Logs/CacheRecordTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/Logs/CacheRecordTest.java @@ -29,7 +29,7 @@ public void testGetRepoName(){ @Test public void testSetRepoSize(){ record.setRepoSize("5MB"); - assertEquals(record.getRepoSize(),"5MB"); + assertEquals("5MB",record.getRepoSize()); } @Test @@ -37,7 +37,7 @@ public void testSetMaintenanceType(){ assertEquals(record.getMaintenanceType(),TaskType.GC.getTaskName()); record.setMaintenanceType(TaskType.PREFETCH.getTaskName()); - assertEquals(record.getMaintenanceType(),TaskType.PREFETCH.getTaskName()); + assertEquals(TaskType.PREFETCH.getTaskName(),record.getMaintenanceType()); } @Test @@ -47,7 +47,7 @@ public void testSetTimeOfExecution(){ Date date = new Date(timeOfExecution * 1000L); SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm"); - assertEquals(record.getTimeOfExecution(),sdf.format(date)); + assertEquals(sdf.format(date),record.getTimeOfExecution()); } @Test @@ -63,7 +63,7 @@ public void testSetExecutionStatus(){ public void testSetExecutionDuration(){ long duration = System.currentTimeMillis(); record.setExecutionDuration(duration); - assertEquals(record.getExecutionDuration(),duration); + assertEquals(duration,record.getExecutionDuration()); } @Test @@ -82,7 +82,7 @@ public void testInsertMaintenanceData(){ record.insertMaintenanceData(looseObjectsRecord); for(Map.Entry> entry : record.maintenanceData.entrySet()){ - assertEquals(entry.getValue().size(),1); + assertEquals(1,entry.getValue().size()); } } @@ -133,15 +133,14 @@ public void copyCacheRecord(){ record.setRepoSize("5MB"); CacheRecord copyCacheRecord = new CacheRecord(record); - assertEquals(copyCacheRecord.getExecutionDuration(),duration); + assertEquals(duration,copyCacheRecord.getExecutionDuration()); assertTrue(record.getExecutionStatus()); - assertEquals(copyCacheRecord.getMaintenanceType(),TaskType.GC.getTaskName()); - assertEquals(copyCacheRecord.getRepoSize(),"5MB"); - + assertEquals(TaskType.GC.getTaskName(),copyCacheRecord.getMaintenanceType()); + assertEquals("5MB",copyCacheRecord.getRepoSize()); Date date = new Date(timeOfExecution * 1000L); SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm"); - assertEquals(copyCacheRecord.getTimeOfExecution(),sdf.format(date)); + assertEquals(sdf.format(date),copyCacheRecord.getTimeOfExecution()); } diff --git a/src/test/java/jenkins/plugins/git/maintenance/Logs/RecordListTest.java b/src/test/java/jenkins/plugins/git/maintenance/Logs/RecordListTest.java new file mode 100644 index 0000000000..cfc52ec9cd --- /dev/null +++ b/src/test/java/jenkins/plugins/git/maintenance/Logs/RecordListTest.java @@ -0,0 +1,35 @@ +package jenkins.plugins.git.maintenance.Logs; + +import jenkins.plugins.git.maintenance.TaskType; +import org.junit.Before; +import org.junit.Test; + +import java.util.List; + +import static org.junit.Assert.*; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; + +public class RecordListTest { + + RecordList recordList; + @Before + public void setUp() throws Exception { + recordList = new RecordList(); + } + + @Test + public void testGetAllMaintenanceRecords() { + assertThat(recordList.getMaintenanceRecords(),instanceOf(List.class)); + } + + @Test + public void testAddRecord() { + CacheRecord record = new CacheRecord("git-plugin", TaskType.GC.getTaskName()); + recordList.addRecord(record); + + + + } + +} From c0bf7c9f0eba255e491ac64e776f2c4ae1a17faf Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Sat, 27 Aug 2022 15:15:51 +0530 Subject: [PATCH 104/146] added RecordListTest --- .../git/maintenance/Logs/RecordList.java | 13 +++- .../git/maintenance/Logs/RecordListTest.java | 77 ++++++++++++++++++- 2 files changed, 85 insertions(+), 5 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java index 8aea3e1454..8e5ae3728d 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java @@ -15,14 +15,15 @@ public RecordList(){ cacheSet = new HashSet<>(); } - public List getMaintenanceRecords(){ + List getMaintenanceRecords(){ return new LinkedList<>(maintenanceRecords); } - public void addRecord(CacheRecord cacheRecord){ + void addRecord(CacheRecord cacheRecord){ String repoName = cacheRecord.getRepoName(); + Set cacheSet = getCacheSet(); if(cacheSet.contains(repoName)){ - // need to add cache to existing record + // adding record to existing cache list Iterator itr = maintenanceRecords.iterator(); CacheRecord record; @@ -57,7 +58,7 @@ record = itr.next(); cacheSet.add(repoName); } - public List getAllMaintenanceRecordsForSingleCache(String cacheName) { + List getAllMaintenanceRecordsForSingleCache(String cacheName) { List allRecords = null; Iterator itr = maintenanceRecords.iterator(); @@ -73,4 +74,8 @@ record = itr.next(); return allRecords; } + + Set getCacheSet(){ + return this.cacheSet; + } } diff --git a/src/test/java/jenkins/plugins/git/maintenance/Logs/RecordListTest.java b/src/test/java/jenkins/plugins/git/maintenance/Logs/RecordListTest.java index cfc52ec9cd..5a451db138 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/Logs/RecordListTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/Logs/RecordListTest.java @@ -13,6 +13,8 @@ public class RecordListTest { RecordList recordList; + + String cacheName = "git-plugin"; @Before public void setUp() throws Exception { recordList = new RecordList(); @@ -25,11 +27,84 @@ public void testGetAllMaintenanceRecords() { @Test public void testAddRecord() { - CacheRecord record = new CacheRecord("git-plugin", TaskType.GC.getTaskName()); + // Testing when adding the first cache record + CacheRecord record = new CacheRecord(cacheName, TaskType.GC.getTaskName()); + record.setExecutionStatus(true); + recordList.addRecord(record); + assertEquals(1,recordList.getMaintenanceRecords().size()); + assertTrue(recordList.getCacheSet().contains(cacheName)); + + // Testing the head of the List. + CacheRecord headRecord = recordList.getMaintenanceRecords().get(0); + assertEquals(TaskType.GC.getTaskName(),headRecord.getMaintenanceType()); + assertEquals(cacheName,headRecord.getRepoName()); + assertTrue(headRecord.getExecutionStatus()); + + + // Testing when adding more records for same cache + CacheRecord gcCacheRecord = new CacheRecord(cacheName,TaskType.GC.getTaskName()); + CacheRecord prefetchRecord = new CacheRecord(cacheName,TaskType.PREFETCH.getTaskName()); + CacheRecord commitGraphRecord = new CacheRecord(cacheName,TaskType.COMMIT_GRAPH.getTaskName()); + CacheRecord incrementalRepackRecord = new CacheRecord(cacheName,TaskType.INCREMENTAL_REPACK.getTaskName()); + CacheRecord looseObjectsRecord = new CacheRecord(cacheName,TaskType.LOOSE_OBJECTS.getTaskName()); + looseObjectsRecord.setExecutionStatus(false); + + recordList.addRecord(gcCacheRecord); + recordList.addRecord(prefetchRecord); + recordList.addRecord(commitGraphRecord); + recordList.addRecord(incrementalRepackRecord); + recordList.addRecord(looseObjectsRecord); + + assertEquals(1,recordList.getMaintenanceRecords().size()); + assertTrue(recordList.getCacheSet().contains(cacheName)); + + // Here the head of the List Cache data will be updated with the latest maintenance data. + headRecord = recordList.getMaintenanceRecords().get(0); + assertEquals(cacheName,headRecord.getRepoName()); + assertEquals(TaskType.LOOSE_OBJECTS.getTaskName(),headRecord.getMaintenanceType()); + assertFalse(headRecord.getExecutionStatus()); + } + + @Test + public void testGetAllMaintenanceRecordsForSingleCache(){ + // Adding record for new Cache + CacheRecord record = new CacheRecord(cacheName, TaskType.GC.getTaskName()); + record.setTimeOfExecution(1661593520); recordList.addRecord(record); + CacheRecord gcCacheRecord = new CacheRecord(cacheName,TaskType.GC.getTaskName()); + CacheRecord prefetchRecord = new CacheRecord(cacheName,TaskType.PREFETCH.getTaskName()); + CacheRecord commitGraphRecord = new CacheRecord(cacheName,TaskType.COMMIT_GRAPH.getTaskName()); + CacheRecord incrementalRepackRecord = new CacheRecord(cacheName,TaskType.INCREMENTAL_REPACK.getTaskName()); + CacheRecord looseObjectsRecord = new CacheRecord(cacheName,TaskType.LOOSE_OBJECTS.getTaskName()); + + // set the TimeofExecution for each cache + gcCacheRecord.setTimeOfExecution(1661552520); + prefetchRecord.setTimeOfExecution(1661553520); + commitGraphRecord.setTimeOfExecution(1661552120); + incrementalRepackRecord.setTimeOfExecution(1661572520); + looseObjectsRecord.setTimeOfExecution(1661512520); + + recordList.addRecord(gcCacheRecord); + recordList.addRecord(prefetchRecord); + recordList.addRecord(commitGraphRecord); + recordList.addRecord(incrementalRepackRecord); + recordList.addRecord(looseObjectsRecord); + + List allMaintenanceRecordsForSingleCache = recordList.getAllMaintenanceRecordsForSingleCache(cacheName); + + assertEquals(6,allMaintenanceRecordsForSingleCache.size()); + + boolean isSorted = true; + for(int i=1;i allMaintenanceRecordsForSingleCache.get(i).timeOfExecution){ + isSorted = false; + break; + } + } + assertTrue(isSorted); } } From 0a703c7e55738a7a2f5219b3aa3f078526f51ef9 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Sat, 27 Aug 2022 15:16:17 +0530 Subject: [PATCH 105/146] fixed null name check error --- .../java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java index 1f692e018d..aa0690621d 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java @@ -90,7 +90,7 @@ public void setExecutionDuration(long executionDuration) { } public void insertMaintenanceData(CacheRecord record){ - if(record != null && maintenanceData != null && this.repoName.equals(record.getRepoName())) { + if(record != null && maintenanceData != null) { LinkedList list = maintenanceData.get(record.getMaintenanceType()); list.addFirst(record); // Maximum storage of 5 Maintenance Records per Cache. From 6cf7ca1a5a4fbb0d09b09beb24fa36394d097b4d Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Sat, 27 Aug 2022 15:26:50 +0530 Subject: [PATCH 106/146] updated index while checking sort in test file --- .../jenkins/plugins/git/maintenance/Logs/RecordListTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/jenkins/plugins/git/maintenance/Logs/RecordListTest.java b/src/test/java/jenkins/plugins/git/maintenance/Logs/RecordListTest.java index 5a451db138..906f7205b6 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/Logs/RecordListTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/Logs/RecordListTest.java @@ -76,7 +76,7 @@ public void testGetAllMaintenanceRecordsForSingleCache(){ CacheRecord prefetchRecord = new CacheRecord(cacheName,TaskType.PREFETCH.getTaskName()); CacheRecord commitGraphRecord = new CacheRecord(cacheName,TaskType.COMMIT_GRAPH.getTaskName()); CacheRecord incrementalRepackRecord = new CacheRecord(cacheName,TaskType.INCREMENTAL_REPACK.getTaskName()); - CacheRecord looseObjectsRecord = new CacheRecord(cacheName,TaskType.LOOSE_OBJECTS.getTaskName()); + CacheRecord looseObjectsRecord = new CacheRecord(cacheName,TaskType.LOOSE_OBJECTS.getTaskName()); // This is the latest cache record // set the TimeofExecution for each cache gcCacheRecord.setTimeOfExecution(1661552520); @@ -98,7 +98,7 @@ public void testGetAllMaintenanceRecordsForSingleCache(){ boolean isSorted = true; for(int i=1;i allMaintenanceRecordsForSingleCache.get(i).timeOfExecution){ + if(allMaintenanceRecordsForSingleCache.get(i).timeOfExecution > allMaintenanceRecordsForSingleCache.get(i-1).timeOfExecution){ isSorted = false; break; } From aea67183c90628507beb2f1fe5e46c01e30c5223 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Fri, 2 Sep 2022 21:05:51 +0530 Subject: [PATCH 107/146] javadoc Task.java --- .../jenkins/plugins/git/maintenance/Task.java | 48 ++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/Task.java b/src/main/java/jenkins/plugins/git/maintenance/Task.java index 6b160bb711..389c030c07 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Task.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Task.java @@ -1,18 +1,33 @@ package jenkins.plugins.git.maintenance; -import antlr.ANTLRException; - +/** + * POJO to store configuration for maintenance tasks. + * @since TODO + * + * @author Hrushikesh Rao + */ public class Task { private TaskType task; private String cronSyntax; private boolean isConfigured; + /** + * Initialize a maintenance task object. + * + * @param task {@link TaskType}. + */ public Task(TaskType task){ // Can add default cron syntax recommended by git documentation this.task = task; } + /** + * A convenience constructor that copies the Task object. + * + * @param copyTask task object. + * + */ public Task(Task copyTask){ // Used for copying the task; this(copyTask.getTaskType()); @@ -20,24 +35,53 @@ public Task(Task copyTask){ setIsTaskConfigured(copyTask.getIsTaskConfigured()); } + /** + * Gets the TaskType enum. + * + * @return TaskType {@link TaskType}. + */ public TaskType getTaskType(){ return this.task; } + /** + * Gets the name of the maintenance task. + * + * @return maintenance task name. + */ public String getTaskName(){ return this.task.getTaskName(); } + /** + * + * @return cron syntax configured for a maintenance task. + */ public String getCronSyntax(){ return this.cronSyntax; } + /** + * Toggle the state of execution of maintenance task. + * + * @param isConfigured if true, corresponding task is configured and executed using cron syntax. + */ public void setIsTaskConfigured(boolean isConfigured){ this.isConfigured = isConfigured; } + /** + * + * @return A boolean to check maintenance task is configured by administrator. + */ public boolean getIsTaskConfigured(){ return this.isConfigured; } + /** + * Configure the Cron Syntax + * + * @param cronSyntax cron syntax as String + * + */ public void setCronSyntax(String cronSyntax){ this.cronSyntax = cronSyntax; } From dab58c03e305842c34f8edaecefddd83a4a3ebba Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Fri, 2 Sep 2022 22:30:29 +0530 Subject: [PATCH 108/146] javadoc MaintenanceTaskConfiguration.java --- .../MaintenanceTaskConfiguration.java | 73 ++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java index cc145acbe1..78d701d6b9 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java @@ -23,14 +23,33 @@ import java.util.logging.Logger; import java.util.stream.Collectors; +/** + * MaintenanceTaskConfiguration is responsible for creating tasks,fetching tasks, storing the configuration in Jenkins. It extends the + * {@link GlobalConfiguration} class. + * @since TODO + * + * @author Hrushikesh Rao + */ @Extension public class MaintenanceTaskConfiguration extends GlobalConfiguration { + /** + * It is the core data structure which stores all maintenance tasks. + * A map ensure the efficient data access. The {@link TaskType} is key and {@link Task} is value. + * + */ private Map maintenanceTasks; private boolean isGitMaintenanceRunning; private static final Logger LOGGER = Logger.getLogger(MaintenanceTaskConfiguration.class.getName()); + /** + * The constructor checks if a maintenanceTaskConfiguration.xml file is present on Jenkins. + * This xml file contains maintenance data configured by the administrator. + * If file is present, the data is loaded from the file. The file would be missing if administrators never configured maintenance task on Jenkins. + * If file is missing a data structure is created by calling {@link MaintenanceTaskConfiguration#configureMaintenanceTasks()}. + * + */ public MaintenanceTaskConfiguration(){ LOGGER.log(Level.FINE,"Loading git-maintenance configuration if present on jenkins controller."); @@ -43,6 +62,10 @@ public MaintenanceTaskConfiguration(){ LOGGER.log(Level.FINE,"Loaded git maintenance configuration successfully."); } } + + /** + * Initializes a data structure if configured for first time. The data structure is used to store and fetch maintenance configuration. + */ private void configureMaintenanceTasks(){ // check git version and based on git version, add the maintenance tasks to the list // Can add default cron syntax for maintenance tasks. @@ -55,6 +78,11 @@ private void configureMaintenanceTasks(){ maintenanceTasks.put(TaskType.INCREMENTAL_REPACK,new Task(TaskType.INCREMENTAL_REPACK)); } + /** + * Gets a copy of list of Maintenance Tasks. + * + * @return List of {@link Task}. + */ public List getMaintenanceTasks(){ List maintenanceTasks = new ArrayList<>(); for(Map.Entry entry : this.maintenanceTasks.entrySet()){ @@ -63,6 +91,12 @@ public List getMaintenanceTasks(){ return ImmutableList.copyOf(maintenanceTasks); } + /** + * Set the cron Syntax of a maintenance task. + * + * @param taskType type of maintenance task. + * @param cronSyntax cron syntax corresponding to task. + */ public void setCronSyntax(TaskType taskType, String cronSyntax){ Task updatedTask = maintenanceTasks.get(taskType); updatedTask.setCronSyntax(cronSyntax); @@ -70,18 +104,42 @@ public void setCronSyntax(TaskType taskType, String cronSyntax){ LOGGER.log(Level.FINE,"Assigned " + cronSyntax + " to " + taskType.getTaskName()); } + /** + * Returns the status of git maintenance i.e. is it configured or not. + * + * @return A boolean if git maintenance is configured globally. + */ public boolean getIsGitMaintenanceRunning(){ return isGitMaintenanceRunning; } + /** + * Set the execution status of git maintenance globally. If false, the git maintenance is not executed on any cache. + * + * @param executionStatus a boolean to set the global git maintenance. + */ public void setIsGitMaintenanceRunning(boolean executionStatus){isGitMaintenanceRunning = executionStatus;} + /** + * Maintenance task state can be changed by toggling the isConfigured boolean variable present in {@link Task} class. + * If isConfigured is true, the maintenance task is executed when corresponding cronSyntax is valid else task is not executed at all. + * + * @param taskType The type of maintenance task. + * @param isConfigured The state of execution of maintenance Task. + */ public void setIsTaskConfigured(TaskType taskType, boolean isConfigured){ Task task = maintenanceTasks.get(taskType); task.setIsTaskConfigured(isConfigured); LOGGER.log(Level.FINE,taskType.getTaskName() + " execution status: " + isConfigured); } + /** + * Validates the input cron syntax. + * + * @param cron Cron syntax as String. + * @return Empty string if no error, else a msg describing error in cron syntax. + * @throws ANTLRException during incorrect cron input. + */ public static String checkSanity(String cron) throws ANTLRException { try { CronTab cronTab = new CronTab(cron.trim()); @@ -94,6 +152,11 @@ public static String checkSanity(String cron) throws ANTLRException { } } + /** + * Returns the git version used for maintenance. + * + * @return the git version used for maintenance. + */ static List getGitVersion(){ final TaskListener procListener = StreamTaskListener.fromStderr(); @@ -111,13 +174,21 @@ static List getGitVersion(){ } final String[] fields = versionOutput.split(" ")[2].replaceAll("msysgit.", "").replaceAll("windows.", "").split("\\."); + // Eg: [2, 31, 4] // 0th index is Major Version. // 1st index is Minor Version. // 2nd index is Patch Version. return Arrays.stream(fields).map(Integer::parseInt).collect(Collectors.toList()); } - + /** + * Checks if the git version used for maintenance is matching at least the requirements passed by the method parameters. + * + * @param neededMajor Major git version. + * @param neededMinor Minor git version. + * @param neededPatch Patch git version. + * @return a boolean that checks the git version used for maintenance is greater than or equal to the required version. + */ public static boolean gitVersionAtLeast(int neededMajor, int neededMinor, int neededPatch) { List fields = getGitVersion(); final int gitMajor = fields.get(0); From 48c8b41036f37a0df9c26bf35690f963cb77f3c6 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Fri, 2 Sep 2022 22:48:30 +0530 Subject: [PATCH 109/146] javadoc TaskType.java --- .../plugins/git/maintenance/TaskType.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskType.java b/src/main/java/jenkins/plugins/git/maintenance/TaskType.java index eb9cc07c2b..a677e83795 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskType.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskType.java @@ -1,5 +1,15 @@ package jenkins.plugins.git.maintenance; +/** + * TaskType describes the type of maintenance task. There are 5 types of maintenance tasks. They are- + *
    + *
  • Prefetch
  • + *
  • Garbage Collection
  • + *
  • Commit Graph
  • + *
  • Loose Objects
  • + *
  • Incremental Repack
  • + *
+ */ public enum TaskType { GC("Gc"), PREFETCH("Prefetch"), @@ -8,10 +18,19 @@ public enum TaskType { INCREMENTAL_REPACK("Incremental Repack"); String taskName; + + /** + * + * @param taskName Assign a name for maintenance task. + */ TaskType(String taskName){ this.taskName = taskName; } + /** + * + * @return name of the maintenance task. + */ public String getTaskName(){ return this.taskName; } From 42f9cd4d9b0681ee216f6e14cef49e0bb8207566 Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Sat, 3 Sep 2022 11:05:34 -0600 Subject: [PATCH 110/146] Use most recent git client incremental --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4ec6e8b75e..2790ee7d18 100644 --- a/pom.xml +++ b/pom.xml @@ -102,7 +102,7 @@ org.jenkins-ci.plugins git-client - 3.11.1-rc3100.a_658da_12c901 + 3.12.0-rc3254.d007744db_513 org.jenkins-ci.plugins From ce68d14a7cbdac133b63dc8bd908812ad6ad8bb4 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Fri, 2 Sep 2022 23:07:40 +0530 Subject: [PATCH 111/146] updated gc to garbage collection --- src/main/java/jenkins/plugins/git/maintenance/TaskType.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskType.java b/src/main/java/jenkins/plugins/git/maintenance/TaskType.java index a677e83795..1074a8f9ff 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskType.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskType.java @@ -9,9 +9,11 @@ *
  • Loose Objects
  • *
  • Incremental Repack
  • * + * + * @author Hrushikesh Rao */ public enum TaskType { - GC("Gc"), + GC("Garbage Collection"), PREFETCH("Prefetch"), COMMIT_GRAPH("Commit Graph"), LOOSE_OBJECTS("Loose Objects"), From aa27fc78031fc2f38071640fa965e368da734fef Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Mon, 5 Sep 2022 12:59:04 +0530 Subject: [PATCH 112/146] fixed expand btn in table --- .../plugins/git/maintenance/MaintenanceUI/table.jelly | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/table.jelly b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/table.jelly index 112b74530a..b01f603e41 100644 --- a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/table.jelly +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/table.jelly @@ -53,9 +53,10 @@ ${%Repo Name} ${%Repo Size} ${%Task} - ${%Previous Execution} + ${%Time} ${%Status} - ${%Execution Time} + ${%Execution Time} (ms) + Expand @@ -93,7 +94,7 @@ pagingType: 'numbers', // Page number button only, }); - jQuery('#fixed .expand').on('click',function(){ + jQuery('#fixed').on('click','.expand',function(){ var tr = jQuery(this).closest('tr'); var row = table.row(tr); if (row.child.isShown()) { From 89865b7b036c5f745ca3dc53eb974b575244bc55 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Mon, 5 Sep 2022 13:11:07 +0530 Subject: [PATCH 113/146] javadoc TaskScheduler.java --- .../git/maintenance/TaskScheduler.java | 65 +++++++++++++++++-- 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index db562a31ef..ff5781421d 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -15,23 +15,43 @@ import java.util.logging.Level; import java.util.logging.Logger; +/** + * TaskScheduler is responsible for scheduling maintenance tasks. It validates if a task is configured & verifies cron syntax before scheduling. + * TaskScheduler acts as a producer by adding the appropriate task into a maintenance queue. + * + * @author Hrushikesh Rao + */ public class TaskScheduler { private MaintenanceTaskConfiguration config; + + /** + * Stores the order of execution of maintenance tasks. + */ private List maintenanceQueue; + + /** + * {@link TaskExecutor} executes the maintenance tasks on all the caches. + */ private Thread taskExecutor; private TaskExecutor taskExecutorRunnable; private static final Logger LOGGER = Logger.getLogger(TaskScheduler.class.getName()); private static final Random random = new Random(); + /** + * Loads the maintenance configuration configured by the administrator. Also initializes an empty maintenance queue. + */ public TaskScheduler(){ this.config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); this.maintenanceQueue = new LinkedList<>(); LOGGER.log(Level.FINE,"TaskScheduler class Initialized."); } - public void scheduleTasks() { + /** + * Schedules maintenance tasks on caches. + */ + void scheduleTasks() { if(config != null) { if (!isGitMaintenanceTaskRunning(config)) { // Logs ever 1 min. Need to check performance impact. @@ -39,8 +59,8 @@ public void scheduleTasks() { return; } - List configuredTasks = config.getMaintenanceTasks(); - addTasksToQueue(configuredTasks); + List maintenanceTasks = config.getMaintenanceTasks(); + addTasksToQueue(maintenanceTasks); // Option of Using the same thread for executing more maintenance task, or create a new thread the next minute and execute the maintenance task. createTaskExecutorThread(); }else{ @@ -49,6 +69,12 @@ public void scheduleTasks() { } + /** + * Checks for duplication of maintenance task in the queue. + * + * @param task type of maintenance task ({@link Task}). + * @return a boolean to see if a task is already present in maintenance queue. + */ boolean checkIsTaskInQueue(Task task){ boolean isTaskInQueue = maintenanceQueue.stream().anyMatch(queuedTask -> queuedTask.getTaskType().equals(task.getTaskType())); if(isTaskInQueue){ @@ -57,6 +83,9 @@ boolean checkIsTaskInQueue(Task task){ return isTaskInQueue; } + /** + * A new Thread {@link TaskExecutor} is created which executes the maintenance task on caches. + */ void createTaskExecutorThread(){ // Create a new thread and execute the tasks present in the queue; if(!maintenanceQueue.isEmpty() && (taskExecutor == null || !taskExecutor.isAlive())) { @@ -68,10 +97,15 @@ void createTaskExecutorThread(){ } } - void addTasksToQueue(List configuredTasks){ + /** + * Iterates through all the maintenance tasks and adds the task to queue if valid. + * + * @param maintenanceTasks List of maintenance tasks {@link Task} + */ + void addTasksToQueue(List maintenanceTasks){ boolean isTaskExecutable; - for(Task task : configuredTasks){ + for(Task task : maintenanceTasks){ try { if(!task.getIsTaskConfigured() || checkIsTaskInQueue(task)) continue; @@ -89,10 +123,22 @@ void addTasksToQueue(List configuredTasks){ } } + /** + * Checks if global git maintenance is configured. + * @param config {@link MaintenanceTaskConfiguration}. + * @return Global git maintenance is configured or not. + */ boolean isGitMaintenanceTaskRunning(MaintenanceTaskConfiguration config){ return config.getIsGitMaintenanceRunning(); } + /** + * Returns CronTabList for a cronSyntax. + * + * @param cronSyntax cron syntax for maintenance task. + * @return {@link CronTabList} + * @throws ANTLRException + */ CronTabList getCronTabList(String cronSyntax) throws ANTLRException { // Random number between 0 & 100000 String seed = String.valueOf((random.nextInt(100000))); @@ -100,6 +146,12 @@ CronTabList getCronTabList(String cronSyntax) throws ANTLRException { return new CronTabList(Collections.singletonList(cronTab)); } + /** + * Checks if the cron syntax matches the current time. Returns true if valid. + * + * @param cronTabList {@link CronTabList} + * @return maintenance task should be scheduled or not. + */ boolean checkIsTaskExecutable(CronTabList cronTabList){ boolean isTaskExecutable = false; @@ -110,6 +162,9 @@ boolean checkIsTaskExecutable(CronTabList cronTabList){ return isTaskExecutable; } + /** + * Terminates the {@link TaskExecutor} thread to stop executing maintenance on caches. Also empties the maintenance queue. + */ void terminateMaintenanceTaskExecution(){ this.maintenanceQueue = new LinkedList<>(); if(taskExecutor != null && taskExecutor.isAlive()) From b06a83ccae24fd6900e897a3a26e58f1fbf4adc2 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Mon, 5 Sep 2022 13:50:41 +0530 Subject: [PATCH 114/146] javadoc TaskExecutor.java --- .../plugins/git/maintenance/TaskExecutor.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index 9fd8ba357d..4a66fc5558 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -20,16 +20,35 @@ import java.util.logging.Level; import java.util.logging.Logger; +/** + * + */ public class TaskExecutor implements Runnable { + /** + * Boolean to toggle the state of execution of thread. + */ private volatile boolean isThreadAlive; + + /** + * Type of maintenance task being executed on caches. + */ Task maintenanceTask; + + /** + * List of caches present on Jenkins controller. + */ private List caches; XmlSerialize xmlSerialize; private static final Logger LOGGER = Logger.getLogger(TaskExecutor.class.getName()); + /** + * Initializes the thread to execute a maintenance task. + * + * @param maintenanceTask Type of maintenance task required for execution. + */ public TaskExecutor(Task maintenanceTask){ this.maintenanceTask = new Task(maintenanceTask); caches = getCaches(); @@ -38,6 +57,9 @@ public TaskExecutor(Task maintenanceTask){ LOGGER.log(Level.FINE,"New Thread created to execute " + maintenanceTask.getTaskName()); } + /** + * Executes the maintenance task by iterating through the all caches on Jenkins controller. + */ @Override public void run() { @@ -57,6 +79,13 @@ public void run() { } + /** + * Executes maintenance task on a single cache. The cache is first locked and then undergoes git maintenance. + * + * @param cacheFile File of a single cache. + * @param lock Lock for a single cache. + * @throws InterruptedException When GitClient is interrupted during maintenance execution. + */ void executeMaintenanceTask(File cacheFile,Lock lock) throws InterruptedException{ TaskType taskType = maintenanceTask.getTaskType(); @@ -98,6 +127,13 @@ void executeMaintenanceTask(File cacheFile,Lock lock) throws InterruptedExceptio xmlSerialize.addMaintenanceRecord(createRecord(cacheFile,taskType,executionStatus,executionDuration)); // Stores the record in jenkins. } + /** + * Executes git maintenance on single cache for git versions >= 2.30 .{@link TaskType} defines the type of maintenance task. + * + * @param gitClient {@link GitClient} on a single cache. + * @param taskType Type of maintenance task. + * @throws InterruptedException When GitClient is interrupted during maintenance execution. + */ void executeGitMaintenance(GitClient gitClient,TaskType taskType) throws InterruptedException { // checking git version for every cache. Reason is because in the UI, the git version can be changed anytime. LOGGER.log(Level.FINE,"Git version >= 2.30.0 detected. Using official git maintenance command."); @@ -116,6 +152,14 @@ void executeGitMaintenance(GitClient gitClient,TaskType taskType) throws Interru terminateThread(); } } + + /** + * Executes git maintenance on single cache for git versions < 2.30 .{@link TaskType} defines the type of maintenance task. + * + * @param gitClient {@link GitClient} on single cache. + * @param taskType Type of maintenance task. + * @throws InterruptedException When GitClient is interrupted during maintenance execution. + */ void executeLegacyGitMaintenance(GitClient gitClient,TaskType taskType) throws InterruptedException{ LOGGER.log(Level.FINE,"Git version < 2.30.0 detected. Using legacy git maintenance commands"); @@ -157,16 +201,35 @@ else if(taskType.equals(TaskType.COMMIT_GRAPH)) } } + /** + * Checks if the git version used for maintenance is matching the requirements passed by the method parameters. + * + * @param neededMajor Major git version. + * @param neededMinor Minor git version. + * @param neededPatch Patch git version. + * @return a boolean that checks the git version used for maintenance is greater than or equal to the required version. + */ boolean gitVersionAtLeast(int neededMajor, int neededMinor, int neededPatch){ return MaintenanceTaskConfiguration.gitVersionAtLeast(neededMajor,neededMinor,neededPatch); } + /** + * Returns a list of caches present on Jenkins controller. See {@link GitMaintenanceSCM#getCaches()} + * + * @return List of caches on Jenkins controller. + */ List getCaches(){ List caches = GitMaintenanceSCM.getCaches(); LOGGER.log(Level.INFO,"Fetched all caches present on Jenkins Controller."); return caches; } + /** + * Returns {@link GitClient} on a single cache. + * + * @param file File object of a single cache. + * @return GitClient on single cache. + */ GitClient getGitClient(File file){ try { TaskListener listener = new LogTaskListener(LOGGER, Level.FINE); @@ -196,10 +259,22 @@ GitClient getGitClient(File file){ return null; } + /** + * Terminates this thread and stops further execution of maintenance tasks. + */ public void terminateThread(){ isThreadAlive = false; } + /** + * Returns a Record ({@link CacheRecord}) which contains the result of maintenance data on a single cache. + * + * @param cacheFile File object of a single cache. + * @param taskType Type of maintenance task. + * @param executionStatus Whether maintenance task has been executed successfully on a cache. + * @param executionDuration Amount of time taken to execute maintenance task in milliseconds. + * @return {@link CacheRecord} of a single cache. + */ CacheRecord createRecord(File cacheFile, TaskType taskType,boolean executionStatus,long executionDuration){ CacheRecord cacheRecord = new CacheRecord(cacheFile.getName(),taskType.getTaskName()); From 72d1a4d5c1638abd52de47302f0b98b45a8642fa Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Mon, 5 Sep 2022 14:19:42 +0530 Subject: [PATCH 115/146] javadoc GitMaintenanceSCM.java --- .../git/maintenance/GitMaintenanceSCM.java | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java b/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java index b4398ff073..e5468260b0 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java +++ b/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java @@ -10,6 +10,9 @@ import java.util.logging.Level; import java.util.logging.Logger; +/** + * GitMaintenanceSCM is responsible for fetching all caches along with locks on Jenkins controller. It extends {@link AbstractGitSCMSource}. + */ public class GitMaintenanceSCM extends AbstractGitSCMSource { String remote; @@ -19,6 +22,9 @@ protected GitMaintenanceSCM(String remote){ this.remote = remote; } + /** + * Stores the File object and lock for cache. + */ static class Cache { File cache; @@ -28,10 +34,19 @@ static class Cache { this.lock = lock; } + /** + * Return the File object of a cache. + * @return File object of a cache. + */ public File getCacheFile(){ return cache; } + /** + * Returns the lock for a cache. + * + * @return lock for a cache. + */ public Lock getLock(){ return lock; } @@ -47,14 +62,19 @@ public String getRemote() { return remote; } + /** + * Returns a list of {@link Cache}. + * @return A list of {@link Cache}. + */ public static List getCaches(){ Jenkins jenkins = Jenkins.getInstanceOrNull(); + List caches = new ArrayList<>(); if(jenkins == null){ - // Throw error; + LOGGER.log(Level.WARNING,"Internal error. Couldn't get instance of Jenkins."); + return caches; } - List caches = new ArrayList<>(); for (String cacheEntry : getCacheEntries()) { File cacheDir = getCacheDir(cacheEntry,false); Lock cacheLock = getCacheLock(cacheEntry); From 9058f214001c49bbea617177c8a3c76a0d07144e Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Mon, 5 Sep 2022 14:37:15 +0530 Subject: [PATCH 116/146] updated missing javadoc --- .../jenkins/plugins/git/maintenance/GitMaintenanceSCM.java | 2 ++ .../java/jenkins/plugins/git/maintenance/TaskExecutor.java | 3 +++ 2 files changed, 5 insertions(+) diff --git a/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java b/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java index e5468260b0..0ca6f0855e 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java +++ b/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java @@ -12,6 +12,8 @@ /** * GitMaintenanceSCM is responsible for fetching all caches along with locks on Jenkins controller. It extends {@link AbstractGitSCMSource}. + * + * @author Hrushikesh Rao */ public class GitMaintenanceSCM extends AbstractGitSCMSource { diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index 4a66fc5558..5cbfc3710a 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -21,7 +21,10 @@ import java.util.logging.Logger; /** + * TaskExecutor executes the maintenance tasks on all Caches on Jenkins controller. A lock is added to each cache before running maintenance on it. + * It is an independent thread. If a cache is already locked, it skips the maintenance task. {@link GitClient} manages the execution of maintenance. * + * @author Hrushikesh Rao */ public class TaskExecutor implements Runnable { From 7260b7752bf2f8d0c46c26845978ece02c3967a7 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Mon, 5 Sep 2022 14:59:09 +0530 Subject: [PATCH 117/146] check null pointer exception --- .../plugins/git/maintenance/Logs/CacheRecord.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java index aa0690621d..45eb53aafd 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java @@ -92,10 +92,12 @@ public void setExecutionDuration(long executionDuration) { public void insertMaintenanceData(CacheRecord record){ if(record != null && maintenanceData != null) { LinkedList list = maintenanceData.get(record.getMaintenanceType()); - list.addFirst(record); - // Maximum storage of 5 Maintenance Records per Cache. - if(list.size() > 5) - list.removeLast(); + if(list != null) { + list.addFirst(record); + // Maximum storage of 5 Maintenance Records per Cache. + if (list.size() > 5) + list.removeLast(); + } } } From bb21cab85e587569472ed26e462e2c5432db487d Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Mon, 5 Sep 2022 15:24:13 +0530 Subject: [PATCH 118/146] UI fixes --- .../git/maintenance/MaintenanceUI/index.jelly | 13 ++++++------- .../git/maintenance/MaintenanceUI/table.jelly | 1 + 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly index 10168904c2..993c3dc8da 100644 --- a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly @@ -35,15 +35,14 @@ - - +
    +
    +

    Maintenance Records

    + + +
    diff --git a/src/test/java/jenkins/plugins/git/maintenance/Logs/CacheRecordTest.java b/src/test/java/jenkins/plugins/git/maintenance/Logs/CacheRecordTest.java index 40980b23e4..d417573c99 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/Logs/CacheRecordTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/Logs/CacheRecordTest.java @@ -1,5 +1,6 @@ package jenkins.plugins.git.maintenance.Logs; +import io.jenkins.cli.shaded.org.apache.commons.lang.time.DurationFormatUtils; import jenkins.plugins.git.maintenance.TaskType; import org.junit.Before; import org.junit.Test; @@ -63,7 +64,7 @@ public void testSetExecutionStatus(){ public void testSetExecutionDuration(){ long duration = System.currentTimeMillis(); record.setExecutionDuration(duration); - assertEquals(duration,record.getExecutionDuration()); + assertEquals(DurationFormatUtils.formatDuration(duration,"mmm:ss:SSS"),record.getExecutionDuration()); } @Test @@ -133,7 +134,7 @@ public void copyCacheRecord(){ record.setRepoSize("5MB"); CacheRecord copyCacheRecord = new CacheRecord(record); - assertEquals(duration,copyCacheRecord.getExecutionDuration()); + assertEquals(DurationFormatUtils.formatDuration(duration,"mmm:ss:SSS"),copyCacheRecord.getExecutionDuration()); assertTrue(record.getExecutionStatus()); assertEquals(TaskType.GC.getTaskName(),copyCacheRecord.getMaintenanceType()); assertEquals("5MB",copyCacheRecord.getRepoSize()); From 4da3432cc077fe93668fdccbee7229dac7fcf57b Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Tue, 6 Sep 2022 18:54:23 +0530 Subject: [PATCH 120/146] Removed git maintenance legacy api --- .../plugins/git/maintenance/TaskExecutor.java | 102 ++++-------------- .../git/maintenance/TaskExecutorTest.java | 16 --- 2 files changed, 22 insertions(+), 96 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index 5cbfc3710a..3c347b15d8 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -106,11 +106,9 @@ void executeMaintenanceTask(File cacheFile,Lock lock) throws InterruptedExceptio throw new InterruptedException("Git Client couldn't be instantiated"); executionDuration -= System.currentTimeMillis(); - if(gitVersionAtLeast(2,30,0)){ - executeGitMaintenance(gitClient,taskType); - }else{ - executeLegacyGitMaintenance(gitClient,taskType); - } + + executeGitMaintenance(gitClient,taskType); + executionDuration += System.currentTimeMillis(); executionStatus = true; } catch (InterruptedException e) { @@ -131,91 +129,35 @@ void executeMaintenanceTask(File cacheFile,Lock lock) throws InterruptedExceptio } /** - * Executes git maintenance on single cache for git versions >= 2.30 .{@link TaskType} defines the type of maintenance task. + * Executes git maintenance on single cache.{@link TaskType} defines the type of maintenance task. * * @param gitClient {@link GitClient} on a single cache. * @param taskType Type of maintenance task. * @throws InterruptedException When GitClient is interrupted during maintenance execution. */ void executeGitMaintenance(GitClient gitClient,TaskType taskType) throws InterruptedException { - // checking git version for every cache. Reason is because in the UI, the git version can be changed anytime. - LOGGER.log(Level.FINE,"Git version >= 2.30.0 detected. Using official git maintenance command."); - if(taskType.equals(TaskType.GC)){ - gitClient.maintenance("gc"); - }else if(taskType.equals(TaskType.COMMIT_GRAPH)){ - gitClient.maintenance("commit-graph"); - }else if(taskType.equals(TaskType.PREFETCH)){ - gitClient.maintenance("prefetch"); - }else if(taskType.equals(TaskType.INCREMENTAL_REPACK)){ - gitClient.maintenance("incremental-repack"); - }else if(taskType.equals(TaskType.LOOSE_OBJECTS)){ - gitClient.maintenance("loose-objects"); - }else{ - LOGGER.log(Level.WARNING,"Invalid maintenance task."); - terminateThread(); - } - } - - /** - * Executes git maintenance on single cache for git versions < 2.30 .{@link TaskType} defines the type of maintenance task. - * - * @param gitClient {@link GitClient} on single cache. - * @param taskType Type of maintenance task. - * @throws InterruptedException When GitClient is interrupted during maintenance execution. - */ - void executeLegacyGitMaintenance(GitClient gitClient,TaskType taskType) throws InterruptedException{ - LOGGER.log(Level.FINE,"Git version < 2.30.0 detected. Using legacy git maintenance commands"); - - // If git version < 2.18.0 =====> run only gc. - // If git version >= 2.18.0 && git version <=2.19.1 ======> run gc and commit-graph - // If git version >= 2.20.0 && git version < 2.30 ========> run gc , commit-graph && multi-pack-index - - if(gitVersionAtLeast(2,20,0)){ - // execute gc, commit-graph && multi-pack-index - if(taskType.equals(TaskType.GC)){ - gitClient.maintenanceLegacy("gc"); - }else if(taskType.equals(TaskType.INCREMENTAL_REPACK)){ - gitClient.maintenanceLegacy("incremental-repack"); - }else if(taskType.equals(TaskType.COMMIT_GRAPH)){ - gitClient.maintenanceLegacy("commit-graph"); - }else{ - LOGGER.log(Level.INFO,"Cannot execute " + taskType.getTaskName() + " maintenance task due to older git version"); - terminateThread(); - } - }else if(gitVersionAtLeast(2,18,0)){ - // execute gc && commit-graph - if(taskType.equals(TaskType.GC)) - gitClient.maintenanceLegacy("gc"); - else if(taskType.equals(TaskType.COMMIT_GRAPH)) - gitClient.maintenanceLegacy("commit-graph"); - else { - LOGGER.log(Level.INFO, "Cannot execute " + taskType.getTaskName() + " maintenance task due to older git version"); + switch (taskType){ + case GC: + gitClient.maintenance("gc"); + break; + case COMMIT_GRAPH: + gitClient.maintenance("commit-graph"); + break; + case PREFETCH: + gitClient.maintenance("prefetch"); + break; + case INCREMENTAL_REPACK: + gitClient.maintenance("incremental-repack"); + break; + case LOOSE_OBJECTS: + gitClient.maintenance("loose-objects"); + break; + default: + LOGGER.log(Level.WARNING,"Invalid maintenance task."); terminateThread(); - } - }else { - // These are git versions less than 2.18.0 - // execute gc only - if(taskType.equals(TaskType.GC)) - gitClient.maintenanceLegacy("gc"); - else { - LOGGER.log(Level.INFO, "Cannot execute " + taskType.getTaskName() + " maintenance task due to older git version"); - terminateThread(); - } } } - /** - * Checks if the git version used for maintenance is matching the requirements passed by the method parameters. - * - * @param neededMajor Major git version. - * @param neededMinor Minor git version. - * @param neededPatch Patch git version. - * @return a boolean that checks the git version used for maintenance is greater than or equal to the required version. - */ - boolean gitVersionAtLeast(int neededMajor, int neededMinor, int neededPatch){ - return MaintenanceTaskConfiguration.gitVersionAtLeast(neededMajor,neededMinor,neededPatch); - } - /** * Returns a list of caches present on Jenkins controller. See {@link GitMaintenanceSCM#getCaches()} * diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java index 5c60975f58..b8c203e5b3 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java @@ -91,12 +91,6 @@ public void testNullFileInGetGitClient() { assertNull(client); } - // This test is dependent on users machine. - @Test - public void testGitVersionAtLeast(){ - taskExecutor.gitVersionAtLeast(2,1,1); - } - @Test public void testGetCaches(){ assertNotNull(taskExecutor.getCaches()); @@ -112,16 +106,6 @@ public void testExecuteGitMaintenance() throws InterruptedException { taskExecutor.executeGitMaintenance(client,taskType); } - // Test doesn't returns any result - @Test - public void testExecuteLegacyGitMaintenance() throws InterruptedException { - GitMaintenanceSCM.Cache cache = taskExecutor.getCaches().get(0); - File cacheFile = cache.getCacheFile(); - GitClient client = taskExecutor.getGitClient(cacheFile); - - taskExecutor.executeLegacyGitMaintenance(client,taskType); - } - // Test doesn't returns any result @Test public void testRunnable() { From 8240acfcdcf3df84ab2adafe8ccb6111e9849444 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Tue, 6 Sep 2022 21:05:56 +0530 Subject: [PATCH 121/146] removed gitVersionAtLeast method remove unwanted test --- .../MaintenanceTaskConfiguration.java | 30 ------------------- .../MaintenanceTaskConfigurationTest.java | 9 ------ 2 files changed, 39 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java index 78d701d6b9..bb135768d7 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java @@ -180,34 +180,4 @@ static List getGitVersion(){ // 2nd index is Patch Version. return Arrays.stream(fields).map(Integer::parseInt).collect(Collectors.toList()); } - - /** - * Checks if the git version used for maintenance is matching at least the requirements passed by the method parameters. - * - * @param neededMajor Major git version. - * @param neededMinor Minor git version. - * @param neededPatch Patch git version. - * @return a boolean that checks the git version used for maintenance is greater than or equal to the required version. - */ - public static boolean gitVersionAtLeast(int neededMajor, int neededMinor, int neededPatch) { - List fields = getGitVersion(); - final int gitMajor = fields.get(0); - final int gitMinor = fields.get(1); - final int gitPatch = fields.get(2); - - final String versionOutput = StringUtils.join(fields,"."); - if (gitMajor < 1 || gitMajor > 3) { - LOGGER.log(Level.WARNING, "Unexpected git major version " + gitMajor + " parsed from '" + versionOutput + "', field:'" + fields.get(0) + "'"); - } - if (gitMinor < 0 || gitMinor > 50) { - LOGGER.log(Level.WARNING, "Unexpected git minor version " + gitMinor + " parsed from '" + versionOutput + "', field:'" + fields.get(1) + "'"); - } - if (gitPatch < 0 || gitPatch > 20) { - LOGGER.log(Level.WARNING, "Unexpected git patch version " + gitPatch + " parsed from '" + versionOutput + "', field:'" + fields.get(2) + "'"); - } - - return gitMajor > neededMajor || - (gitMajor == neededMajor && gitMinor > neededMinor) || - (gitMajor == neededMajor && gitMinor == neededMinor && gitPatch >= neededPatch); - } } diff --git a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java index c73fe864c6..93c455ab8b 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfigurationTest.java @@ -96,13 +96,4 @@ public void testGetGitVersion(){ assertThat("Patch version out of range", gitVersion.get(2), is(both(greaterThan(-1)).and(lessThan(99)))); } } - - // This test depends on the computers git version. -// @Test -// public void testGitVersionAtLeast(){ -// assertTrue(MaintenanceTaskConfiguration.gitVersionAtLeast()); -// assertTrue(MaintenanceTaskConfiguration.gitVersionAtLeast()); -// assertTrue(MaintenanceTaskConfiguration.gitVersionAtLeast()); -// assertTrue(MaintenanceTaskConfiguration.gitVersionAtLeast()); -// } } From e21ea2b09a0584410f55061b73c8a7c781b88223 Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Tue, 6 Sep 2022 20:11:16 -0600 Subject: [PATCH 122/146] Remove xstream dependency, not required Provided by Jenkins core, no need for a separate dependency. Cause several other transitive dependencies to be included unnecessarily. --- pom.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pom.xml b/pom.xml index 2790ee7d18..5766fad3b4 100644 --- a/pom.xml +++ b/pom.xml @@ -144,11 +144,6 @@ mailer
    - - com.thoughtworks.xstream - xstream - 1.4.19 - io.jenkins.plugins data-tables-api From db03e751ae522aab35eb068fee292e3ffb43e041 Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Tue, 6 Sep 2022 20:46:20 -0600 Subject: [PATCH 123/146] Annotate argument as NonNull Let spotbugs help with checks for null pointer exceptions --- .../plugins/git/maintenance/MaintenanceTaskConfiguration.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java index bb135768d7..573a0cbaf3 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java @@ -2,6 +2,7 @@ import antlr.ANTLRException; import com.google.common.collect.ImmutableList; +import edu.umd.cs.findbugs.annotations.NonNull; import hudson.Extension; import hudson.Launcher; import hudson.model.TaskListener; @@ -140,7 +141,7 @@ public void setIsTaskConfigured(TaskType taskType, boolean isConfigured){ * @return Empty string if no error, else a msg describing error in cron syntax. * @throws ANTLRException during incorrect cron input. */ - public static String checkSanity(String cron) throws ANTLRException { + public static String checkSanity(@NonNull String cron) throws ANTLRException { try { CronTab cronTab = new CronTab(cron.trim()); String msg = cronTab.checkSanity(); From c0d3e98f7bd60bffe77677953fb05f57e7fdedf8 Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Tue, 6 Sep 2022 20:46:46 -0600 Subject: [PATCH 124/146] Remove reordering of imports See CONTRIBUTING file for rationale --- .../plugins/git/AbstractGitSCMSource.java | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java index 7dd422a0ef..4db4f3c938 100644 --- a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java +++ b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java @@ -55,6 +55,27 @@ import hudson.plugins.git.util.GitUtils; import hudson.scm.SCM; import hudson.security.ACL; +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Pattern; import jenkins.model.Jenkins; import jenkins.plugins.git.traits.GitBrowserSCMSourceTrait; import jenkins.plugins.git.traits.GitSCMExtensionTrait; @@ -101,28 +122,6 @@ import org.kohsuke.accmod.restrictions.NoExternalUse; import org.kohsuke.stapler.export.Exported; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.TreeSet; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.regex.Pattern; - /** * Base class for {@link SCMSource} implementations that produce {@link GitSCM} implementations. * From 2bd92136fda1c37204bb375f78d75bea23c4525a Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Tue, 6 Sep 2022 20:50:14 -0600 Subject: [PATCH 125/146] Use correct case in middle of sentence --- .../java/jenkins/plugins/git/maintenance/MaintenanceUI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index 22d911f74f..d258ede50e 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -56,7 +56,7 @@ public String getUrlName() { @Override public String getDescription() { - return "Maintain your Repositories to improve git command performance."; + return "Maintain your repositories to improve git performance."; } public @NonNull String getCategoryName() { From f84a4eea011bd4869da83a0b9980d3daf5dcadc2 Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Tue, 6 Sep 2022 21:53:07 -0600 Subject: [PATCH 126/146] Use heading text consistent with Jenkins configuration --- .../jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly index 993c3dc8da..601436029a 100644 --- a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/index.jelly @@ -5,7 +5,7 @@
    -

    Maintenance Tasks

    +

    Maintenance Tasks

    Git Version: ${it.getGitVersion()}

    ${it.updateGitVersionHelperText()}

    Enter cron syntax to execute maintenance tasks periodically

    From c889e9666ce6b6c600771f0f119ec5f81e445b8f Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Wed, 7 Sep 2022 20:05:08 +0530 Subject: [PATCH 127/146] updated execution status using gitClient --- .../plugins/git/maintenance/TaskExecutor.java | 18 ++++++++++-------- .../git/maintenance/TaskExecutorTest.java | 8 ++++++-- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index 3c347b15d8..8908ba4a2b 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -107,10 +107,9 @@ void executeMaintenanceTask(File cacheFile,Lock lock) throws InterruptedExceptio executionDuration -= System.currentTimeMillis(); - executeGitMaintenance(gitClient,taskType); + executionStatus = executeGitMaintenance(gitClient,taskType); executionDuration += System.currentTimeMillis(); - executionStatus = true; } catch (InterruptedException e) { LOGGER.log(Level.FINE, "Couldn't run " + taskType.getTaskName() + ".Msg: " + e.getMessage()); } finally { @@ -133,29 +132,32 @@ void executeMaintenanceTask(File cacheFile,Lock lock) throws InterruptedExceptio * * @param gitClient {@link GitClient} on a single cache. * @param taskType Type of maintenance task. + * @return Boolean if maintenance has been executed or not. * @throws InterruptedException When GitClient is interrupted during maintenance execution. */ - void executeGitMaintenance(GitClient gitClient,TaskType taskType) throws InterruptedException { + boolean executeGitMaintenance(GitClient gitClient,TaskType taskType) throws InterruptedException { + boolean isExecuted = false; switch (taskType){ case GC: - gitClient.maintenance("gc"); + isExecuted = gitClient.maintenance("gc"); break; case COMMIT_GRAPH: - gitClient.maintenance("commit-graph"); + isExecuted = gitClient.maintenance("commit-graph"); break; case PREFETCH: - gitClient.maintenance("prefetch"); + isExecuted = gitClient.maintenance("prefetch"); break; case INCREMENTAL_REPACK: - gitClient.maintenance("incremental-repack"); + isExecuted = gitClient.maintenance("incremental-repack"); break; case LOOSE_OBJECTS: - gitClient.maintenance("loose-objects"); + isExecuted = gitClient.maintenance("loose-objects"); break; default: LOGGER.log(Level.WARNING,"Invalid maintenance task."); terminateThread(); } + return isExecuted; } /** diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java index b8c203e5b3..71965322ef 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java @@ -21,6 +21,7 @@ import java.util.stream.Collectors; import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; @@ -97,13 +98,16 @@ public void testGetCaches(){ } - // Test doesn't returns any result @Test public void testExecuteGitMaintenance() throws InterruptedException { GitMaintenanceSCM.Cache cache = taskExecutor.getCaches().get(0); File cacheFile = cache.getCacheFile(); GitClient client = taskExecutor.getGitClient(cacheFile); - taskExecutor.executeGitMaintenance(client,taskType); + boolean isExecuted = taskExecutor.executeGitMaintenance(client,taskType); + + // based on the underlying git version it will work. + // If git version < 2.30, tests may fail. + assertThat(isExecuted,is(true)); } // Test doesn't returns any result From 55ed5591b0a35fea10e2ace1d1da64965fb0f042 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Wed, 7 Sep 2022 20:23:05 +0530 Subject: [PATCH 128/146] storing size of cache in Bytes --- .../jenkins/plugins/git/maintenance/Logs/CacheRecord.java | 6 +++--- .../jenkins/plugins/git/maintenance/TaskExecutor.java | 3 +-- .../plugins/git/maintenance/Logs/CacheRecordTest.java | 8 ++++---- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java index 011813c0b6..1b54363736 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java @@ -14,7 +14,7 @@ public class CacheRecord { String repoName; - String repoSize; + long repoSize; String maintenanceType; long timeOfExecution; boolean executionStatus; @@ -48,10 +48,10 @@ public String getRepoName() { return repoName; } - public String getRepoSize() { + public long getRepoSize() { return repoSize; } - public void setRepoSize(String repoSize) { + public void setRepoSize(long repoSize) { this.repoSize = repoSize; } diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index 8908ba4a2b..eef8ff8b22 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -226,8 +226,7 @@ CacheRecord createRecord(File cacheFile, TaskType taskType,boolean executionStat CacheRecord cacheRecord = new CacheRecord(cacheFile.getName(),taskType.getTaskName()); long repoSizeInBytes = FileUtils.sizeOfDirectory(cacheFile); - String repoSize = FileUtils.byteCountToDisplaySize(repoSizeInBytes); // Converts the bytes to KB,MB,GB - cacheRecord.setRepoSize(repoSize); + cacheRecord.setRepoSize(repoSizeInBytes); cacheRecord.setExecutionStatus(executionStatus); if(!executionStatus) cacheRecord.setExecutionDuration(-1); diff --git a/src/test/java/jenkins/plugins/git/maintenance/Logs/CacheRecordTest.java b/src/test/java/jenkins/plugins/git/maintenance/Logs/CacheRecordTest.java index d417573c99..e09c9b8a4c 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/Logs/CacheRecordTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/Logs/CacheRecordTest.java @@ -29,8 +29,8 @@ public void testGetRepoName(){ @Test public void testSetRepoSize(){ - record.setRepoSize("5MB"); - assertEquals("5MB",record.getRepoSize()); + record.setRepoSize(12343); + assertEquals(12343,record.getRepoSize()); } @Test @@ -131,13 +131,13 @@ public void copyCacheRecord(){ record.setExecutionDuration(duration); record.setExecutionStatus(true); record.setTimeOfExecution(timeOfExecution); - record.setRepoSize("5MB"); + record.setRepoSize(12343); CacheRecord copyCacheRecord = new CacheRecord(record); assertEquals(DurationFormatUtils.formatDuration(duration,"mmm:ss:SSS"),copyCacheRecord.getExecutionDuration()); assertTrue(record.getExecutionStatus()); assertEquals(TaskType.GC.getTaskName(),copyCacheRecord.getMaintenanceType()); - assertEquals("5MB",copyCacheRecord.getRepoSize()); + assertEquals(12343,copyCacheRecord.getRepoSize()); Date date = new Date(timeOfExecution * 1000L); SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm"); From 5aa22bc0f475c7f2a363ffed7e6aea387926c993 Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Wed, 7 Sep 2022 20:53:08 +0530 Subject: [PATCH 129/146] displaying cacheSize in MB only --- .../git/maintenance/MaintenanceUI/table.jelly | 41 +++++++++---------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/table.jelly b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/table.jelly index 5f75f4b906..c232f8c0dc 100644 --- a/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/table.jelly +++ b/src/main/resources/jenkins/plugins/git/maintenance/MaintenanceUI/table.jelly @@ -1,5 +1,11 @@ +
    @@ -8,8 +14,8 @@ # - ${%Repo Name} - ${%Repo Size} + ${%Cache Name} + ${%Cache Size} (MB) ${%Task} ${%Time} ${%Status} @@ -27,7 +33,8 @@ ${record.getRepoName()} - ${record.getRepoSize()} + + ${record.getRepoSize()/1000000} ${record.getMaintenanceType()} @@ -36,7 +43,12 @@ ${record.getTimeOfExecution()} - ${record.getExecutionStatus()} + + + + + + ${record.getExecutionDuration()} @@ -51,8 +63,8 @@ # - ${%Repo Name} - ${%Repo Size} + ${%Cache Name} + ${%Cache Size} (MB) ${%Task} ${%Time} ${%Status} @@ -94,9 +106,8 @@ var table = jQuery('#fixed').DataTable({ pagingType: 'numbers',// Page number button only, columnDefs: [ - { "type": "repo-size", targets: [2] }, { "type": "execution-time",targets:[6]} - ] + ], }); jQuery('#fixed').on('click','.expand',function(){ @@ -116,20 +127,6 @@ } }) - jQuery().extend( jQuery().dataTable.ext.type.order, { - "repo-size-asc": function (val_1, val_2) { - // your sorting code here - or a call to a function - console.log("Need to sort Asc") - } - } ); - - jQuery().extend( jQuery().dataTable.ext.type.order, { - "repo-size-desc": function (val_1, val_2) { - // your sorting code here - or a call to a function - console.log("Ned to sort Desc") - } - } ); - // Sorting execution time data in ascending order jQuery().extend( jQuery().dataTable.ext.type.order, { "execution-time-asc": function (val_1, val_2) { From 01e27c3521cfac79436b0887b8929b34cb9ab0fc Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Fri, 9 Sep 2022 01:59:56 +0530 Subject: [PATCH 130/146] update git-client incremental version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5766fad3b4..c66bfd3ace 100644 --- a/pom.xml +++ b/pom.xml @@ -102,7 +102,7 @@ org.jenkins-ci.plugins git-client - 3.12.0-rc3254.d007744db_513 + 3.12.0-rc3261.d57b_11df05a_2 org.jenkins-ci.plugins From 83044e58b2c05bf6a8a3371aeb61cac69544d9b0 Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Sun, 18 Sep 2022 21:51:32 -0600 Subject: [PATCH 131/146] Require git client plugin 3.12.0 Provides maintenance API --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c66bfd3ace..9a8eec5cf1 100644 --- a/pom.xml +++ b/pom.xml @@ -102,7 +102,7 @@ org.jenkins-ci.plugins git-client - 3.12.0-rc3261.d57b_11df05a_2 + 3.12.0 org.jenkins-ci.plugins From 3c1a64a43c5a2a77c0e2ccf6e73215094b6c4a2a Mon Sep 17 00:00:00 2001 From: hrushi20 Date: Sat, 1 Oct 2022 15:19:07 +0530 Subject: [PATCH 132/146] Skipping caches whose size less than 10 MB --- .../jenkins/plugins/git/maintenance/GitMaintenanceSCM.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java b/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java index 0ca6f0855e..f6483a2bba 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java +++ b/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java @@ -2,6 +2,7 @@ import jenkins.model.Jenkins; import jenkins.plugins.git.AbstractGitSCMSource; +import org.apache.commons.io.FileUtils; import java.io.File; import java.util.ArrayList; @@ -80,6 +81,9 @@ public static List getCaches(){ for (String cacheEntry : getCacheEntries()) { File cacheDir = getCacheDir(cacheEntry,false); Lock cacheLock = getCacheLock(cacheEntry); + + // skip caches size less than 10 mb + if(FileUtils.sizeOfDirectory(cacheDir) < 10000000)continue; LOGGER.log(Level.FINE,"Cache Entry " + cacheEntry); caches.add(new Cache(cacheDir,cacheLock)); } From cc5c99017a6b38bab1fb3a51b84554e357491c3f Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Sat, 22 Oct 2022 00:36:13 -0600 Subject: [PATCH 133/146] Minor formatting change --- .../jenkins/plugins/git/maintenance/GitMaintenanceSCM.java | 4 ++-- .../jenkins/plugins/git/maintenance/TaskExecutorTest.java | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java b/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java index f6483a2bba..f8c8ceecfa 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java +++ b/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java @@ -73,8 +73,8 @@ public static List getCaches(){ Jenkins jenkins = Jenkins.getInstanceOrNull(); List caches = new ArrayList<>(); - if(jenkins == null){ - LOGGER.log(Level.WARNING,"Internal error. Couldn't get instance of Jenkins."); + if (jenkins == null){ + LOGGER.log(Level.WARNING,"Internal error. Couldn't get Jenkins instance."); return caches; } diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java index 71965322ef..31e3a55c24 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java @@ -61,6 +61,7 @@ public static void setUp() throws Exception{ SCMFileSystem.of(j.createFreeStyleProject(), new GitSCM(GitSCM.createRepoList(sampleRepo1.toString(), null), Collections.singletonList(new BranchSpec("*/bug/JENKINS-42817")), null, null, Collections.emptyList())); } + @Parameterized.Parameters(name = "{0}") public static Collection permuteMaintenanceTasks(){ From 215f75ceee0e5162f72f89dd292b2a3c1ec0e9e0 Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Sat, 22 Oct 2022 00:36:50 -0600 Subject: [PATCH 134/146] Only log cache reads at FINE level --- src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java index eef8ff8b22..5124db6b1d 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskExecutor.java @@ -167,7 +167,7 @@ boolean executeGitMaintenance(GitClient gitClient,TaskType taskType) throws Inte */ List getCaches(){ List caches = GitMaintenanceSCM.getCaches(); - LOGGER.log(Level.INFO,"Fetched all caches present on Jenkins Controller."); + LOGGER.log(Level.FINE,"Fetched all caches present on Jenkins Controller."); return caches; } From c949c455c1cbbaa7033376f1fcaf56148fe5b607 Mon Sep 17 00:00:00 2001 From: Mark Waite Date: Sat, 22 Oct 2022 00:37:12 -0600 Subject: [PATCH 135/146] Remove System.out.println calls --- .../plugins/git/extensions/impl/CloneOptionHonorRefSpecTest.java | 1 - .../jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java | 1 - .../java/jenkins/plugins/git/maintenance/TaskExecutorTest.java | 1 - 3 files changed, 3 deletions(-) diff --git a/src/test/java/hudson/plugins/git/extensions/impl/CloneOptionHonorRefSpecTest.java b/src/test/java/hudson/plugins/git/extensions/impl/CloneOptionHonorRefSpecTest.java index d963bd4923..834eeddd74 100644 --- a/src/test/java/hudson/plugins/git/extensions/impl/CloneOptionHonorRefSpecTest.java +++ b/src/test/java/hudson/plugins/git/extensions/impl/CloneOptionHonorRefSpecTest.java @@ -105,7 +105,6 @@ public void testRefSpecWithExpandedVariables() throws Exception { if (refSpecExpectedValue == null || refSpecExpectedValue.isEmpty()) { /* Test does not support an empty or null expected value. Skip the test if the expected value is empty or null */ - System.out.println("*** testRefSpecWithExpandedVariables empty expected value for '" + refSpecName + "' ***"); return; } // Create initial commit diff --git a/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java b/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java index b10953577e..1cf2284f39 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java @@ -85,7 +85,6 @@ public void testGetCaches() throws Exception{ // @Test // public void testNoCachesExistsOnJenkinsController(){ // List caches = GitMaintenanceSCM.getCaches(); -//// System.out.println(caches); // assertEquals(0,caches.size()); // } diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java index 31e3a55c24..31532d8971 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java @@ -78,7 +78,6 @@ public static Collection permuteMaintenanceTasks(){ @Test public void testGitClient(){ // Get directory of a single cache. - System.out.println(taskExecutor.getCaches()); assertTrue(taskExecutor.getCaches().size() > 0); GitMaintenanceSCM.Cache cache = taskExecutor.getCaches().get(0); File cacheFile = cache.getCacheFile(); From 5499217cdf33149072e75cc779494eb35270c6b9 Mon Sep 17 00:00:00 2001 From: Pc Date: Sun, 30 Jul 2023 22:01:53 +0530 Subject: [PATCH 136/146] Update test TaskExecutor --- .../git/maintenance/TaskExecutorTest.java | 107 +++++++++++------- 1 file changed, 65 insertions(+), 42 deletions(-) diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java index 31532d8971..5926c702c6 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java @@ -1,23 +1,26 @@ package jenkins.plugins.git.maintenance; -import hudson.plugins.git.BranchSpec; -import hudson.plugins.git.GitSCM; +import hudson.Launcher; +import hudson.model.TaskListener; +import hudson.plugins.git.*; +import hudson.util.StreamTaskListener; import jenkins.model.GlobalConfiguration; import jenkins.plugins.git.GitSampleRepoRule; import jenkins.scm.api.SCMFileSystem; import org.jenkinsci.plugins.gitclient.GitClient; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Test; +import org.junit.*; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.jvnet.hudson.test.JenkinsRule; +import java.io.ByteArrayOutputStream; import java.io.File; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.concurrent.locks.ReentrantLock; +import java.util.logging.Level; import java.util.stream.Collectors; import static org.hamcrest.CoreMatchers.instanceOf; @@ -28,38 +31,18 @@ import static org.junit.Assert.assertTrue; @RunWith(Parameterized.class) -public class TaskExecutorTest { +public class TaskExecutorTest extends AbstractGitRepository { @ClassRule - public static JenkinsRule j = new JenkinsRule(); + public static JenkinsRule rule = new JenkinsRule(); - @ClassRule - public static GitSampleRepoRule sampleRepo1 = new GitSampleRepoRule(); + private Task gitTask; - private static TaskExecutor taskExecutor; - private TaskType taskType; public TaskExecutorTest(TaskType taskType) { - MaintenanceTaskConfiguration config = new MaintenanceTaskConfiguration(); - config.setIsTaskConfigured(taskType, true); - config.setCronSyntax(taskType, "* * * * *"); - List tasks = config.getMaintenanceTasks().stream().filter(Task::getIsTaskConfigured).collect(Collectors.toList()); - Task configuredTask = tasks.get(0); - taskExecutor = new TaskExecutor(configuredTask); - this.taskType = taskType; - } - - @BeforeClass - public static void setUp() throws Exception{ - - sampleRepo1.init(); - sampleRepo1.git("checkout", "-b", "bug/JENKINS-42817"); - sampleRepo1.write("file", "modified"); - sampleRepo1.git("commit", "--all", "--message=dev"); - - // Create caches on Jenkins controller. - SCMFileSystem.of(j.createFreeStyleProject(), new GitSCM(GitSCM.createRepoList(sampleRepo1.toString(), null), Collections.singletonList(new BranchSpec("*/bug/JENKINS-42817")), null, null, Collections.emptyList())); - + this.gitTask = new Task(taskType); + this.gitTask.setCronSyntax("* * * * *"); + this.gitTask.setIsTaskConfigured(true); } @Parameterized.Parameters(name = "{0}") @@ -78,6 +61,7 @@ public static Collection permuteMaintenanceTasks(){ @Test public void testGitClient(){ // Get directory of a single cache. + TaskExecutor taskExecutor = new TestTaskExecutorHelper(gitTask,testGitDir); assertTrue(taskExecutor.getCaches().size() > 0); GitMaintenanceSCM.Cache cache = taskExecutor.getCaches().get(0); File cacheFile = cache.getCacheFile(); @@ -88,44 +72,83 @@ public void testGitClient(){ @Test public void testNullFileInGetGitClient() { - GitClient client = taskExecutor.getGitClient(null); + GitClient client = new TestTaskExecutorHelper(gitTask,null).getGitClient(null); assertNull(client); } @Test public void testGetCaches(){ + TaskExecutor taskExecutor = new TestTaskExecutorHelper(gitTask,testGitDir); assertNotNull(taskExecutor.getCaches()); } - @Test public void testExecuteGitMaintenance() throws InterruptedException { + TaskExecutor taskExecutor = new TestTaskExecutorHelper(gitTask,testGitDir); GitMaintenanceSCM.Cache cache = taskExecutor.getCaches().get(0); File cacheFile = cache.getCacheFile(); GitClient client = taskExecutor.getGitClient(cacheFile); - boolean isExecuted = taskExecutor.executeGitMaintenance(client,taskType); + boolean isExecuted = taskExecutor.executeGitMaintenance(client,gitTask.getTaskType()); // based on the underlying git version it will work. // If git version < 2.30, tests may fail. assertThat(isExecuted,is(true)); } - // Test doesn't returns any result @Test public void testRunnable() { MaintenanceTaskConfiguration config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); config.setIsGitMaintenanceRunning(true); - config.setCronSyntax(taskType,"* * * * *"); - config.setIsTaskConfigured(taskType,true); + config.setCronSyntax(gitTask.getTaskType(),"* * * * *"); + config.setIsTaskConfigured(gitTask.getTaskType(),true); TaskScheduler scheduler = new TaskScheduler(); scheduler.scheduleTasks(); } - +// // Todo Need a way to test termination of execution thread. // @Test // public void testTerminateThread(){ // // } + + class TestTaskExecutorHelper extends TaskExecutor { + + File testGitDir; + public TestTaskExecutorHelper(Task maintenanceTask,File testGitDir) { + super(maintenanceTask); + this.testGitDir = testGitDir; + } + + List getCaches(){ + List caches = new ArrayList<>(); + caches.add(new GitMaintenanceSCM.Cache(testGitDir,new ReentrantLock())); + return caches; + } + } + + static List getGitVersion(){ + + final TaskListener procListener = StreamTaskListener.fromStderr(); + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + try { + new Launcher.LocalLauncher(procListener).launch().cmds("git", "--version").stdout(out).join(); + } catch (IOException | InterruptedException ex) { + throw new RuntimeException("Couldn't fetch git maintenance command"); + } + String versionOutput = ""; + try { + versionOutput = out.toString(StandardCharsets.UTF_8.toString()).trim(); + } catch (UnsupportedEncodingException ue) { + throw new RuntimeException("Unsupported encoding version"); + } + final String[] fields = versionOutput.split(" ")[2].replaceAll("msysgit.", "").replaceAll("windows.", "").split("\\."); + + // Eg: [2, 31, 4] + // 0th index is Major Version. + // 1st index is Minor Version. + // 2nd index is Patch Version. + return Arrays.stream(fields).map(Integer::parseInt).collect(Collectors.toList()); + } } From 7245206e9bc147eee937b9386adcc97b12e63d6f Mon Sep 17 00:00:00 2001 From: Pc Date: Sun, 30 Jul 2023 22:16:21 +0530 Subject: [PATCH 137/146] Update TaskSchedulerTest --- .../java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java index 3ef483d49f..92b6024475 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java @@ -31,7 +31,7 @@ public class TaskSchedulerTest { @Before public void setUp() throws Exception { taskScheduler = new TaskScheduler(); - config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); + config = new MaintenanceTaskConfiguration(); } // Tested all the internal functions of this method From f728ae19dfc8057998f6f1ea17370be1883a4221 Mon Sep 17 00:00:00 2001 From: Pc Date: Mon, 31 Jul 2023 01:50:37 +0530 Subject: [PATCH 138/146] updated GitMaintenanceSCMTest --- .../git/maintenance/GitMaintenanceSCM.java | 4 - .../maintenance/GitMaintenanceSCMTest.java | 97 +++++-------------- 2 files changed, 23 insertions(+), 78 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java b/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java index f8c8ceecfa..701beb1b33 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java +++ b/src/main/java/jenkins/plugins/git/maintenance/GitMaintenanceSCM.java @@ -90,8 +90,4 @@ public static List getCaches(){ return caches; } - - String getCacheEntryForTest(){ - return getCacheEntry(); - } } diff --git a/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java b/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java index 1cf2284f39..bec193df3e 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/GitMaintenanceSCMTest.java @@ -1,111 +1,61 @@ package jenkins.plugins.git.maintenance; +import hudson.plugins.git.AbstractGitRepository; +import hudson.plugins.git.AbstractGitTestCase; import hudson.plugins.git.BranchSpec; import hudson.plugins.git.GitSCM; import hudson.plugins.git.extensions.GitSCMExtension; import jenkins.model.Jenkins; +import jenkins.plugins.git.AbstractGitSCMSource; +import jenkins.plugins.git.AbstractGitSCMSourceTest; import jenkins.plugins.git.GitSampleRepoRule; import jenkins.scm.api.SCMFileSystem; import org.apache.commons.io.FileUtils; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; +import org.junit.*; +import org.junit.jupiter.api.BeforeAll; +import org.junit.rules.TemporaryFolder; import org.jvnet.hudson.test.JenkinsRule; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.configuration.IMockitoConfiguration; import java.io.File; import java.io.IOException; -import java.util.Collections; -import java.util.List; +import java.io.RandomAccessFile; +import java.util.*; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +import java.util.logging.Level; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.*; public class GitMaintenanceSCMTest { @Rule - public GitSampleRepoRule sampleRepo1 = new GitSampleRepoRule(); + public JenkinsRule rule = new JenkinsRule(); - @Rule - public GitSampleRepoRule sampleRepo2 = new GitSampleRepoRule(); - - @Rule - public JenkinsRule j = new JenkinsRule(); - - @After - public void clearAllCaches() throws IOException { - File[] caches = new File(Jenkins.getInstanceOrNull().getRootDir(),"caches").listFiles(); - if(caches != null) - for(File cache : caches){ - FileUtils.deleteDirectory(cache); - } - } @Test public void testGetCaches() throws Exception{ - sampleRepo1.init(); - sampleRepo1.git("checkout", "-b", "bug/JENKINS-42817"); - sampleRepo1.write("file", "modified"); - sampleRepo1.git("commit", "--all", "--message=dev"); - SCMFileSystem.of(j.createFreeStyleProject(), new GitSCM(GitSCM.createRepoList(sampleRepo1.toString(), null), Collections.singletonList(new BranchSpec("*/bug/JENKINS-42817")), null, null, Collections.emptyList())); - sampleRepo2.init(); - sampleRepo2.git("checkout", "-b", "bug/JENKINS-42817"); - sampleRepo2.write("file", "modified"); - sampleRepo2.git("commit", "--all", "--message=dev"); - SCMFileSystem.of(j.createFreeStyleProject(), new GitSCM(GitSCM.createRepoList(sampleRepo2.toString(), null), Collections.singletonList(new BranchSpec("*/bug/JENKINS-42817")), null, null, Collections.emptyList())); + // Cannot test this due to static methods not public, + // AbstractGitSCmSource is in different package + List caches = new ArrayList<>(); + caches.add(new GitMaintenanceSCM.Cache(new File("test.txt"),new ReentrantLock())); - GitMaintenanceSCM[] gitMaintenanceSCMS = new GitMaintenanceSCM[2]; - gitMaintenanceSCMS[0] = new GitMaintenanceSCM(sampleRepo1.toString()); - gitMaintenanceSCMS[1] = new GitMaintenanceSCM(sampleRepo2.toString()); - List caches = GitMaintenanceSCM.getCaches(); + mockStatic(GitMaintenanceSCM.class) + .when(()->GitMaintenanceSCM.getCaches()) + .thenReturn(caches); - for(GitMaintenanceSCM.Cache cache : caches){ - if (cache == null) { - continue; - } - String cacheDir = cache.getCacheFile().getName(); - boolean cachesExists = false; - for(GitMaintenanceSCM gitMaintenanceSCM : gitMaintenanceSCMS){ - cachesExists = gitMaintenanceSCM.getCacheEntryForTest().equals(cacheDir); - assertNull(gitMaintenanceSCM.getCredentialsId()); - if(cachesExists) - break; - } + assertEquals(caches.size(),GitMaintenanceSCM.getCaches().size()); - assertTrue(cachesExists); - } } - // What happens to caches when deleted from jenkins controller. We need to delete the cache even from our HashSet present in AbstactGitSCM class -// @Test -// public void testNoCachesExistsOnJenkinsController(){ -// List caches = GitMaintenanceSCM.getCaches(); -// assertEquals(0,caches.size()); -// } - -// @Test -// public void testGetLockAndCacheFile() throws Exception{ -// sampleRepo1.init(); -// sampleRepo1.git("checkout", "-b", "bug/JENKINS-4283423"); -// sampleRepo1.write("file", "modified"); -// sampleRepo1.git("commit", "--all", "--message=dev"); -// SCMFileSystem.of(j.createFreeStyleProject(), new GitSCM(GitSCM.createRepoList(sampleRepo1.toString(), null), Collections.singletonList(new BranchSpec("*/bug/JENKINS-4283423")), null, null, Collections.emptyList())); -// -// List caches = GitMaintenanceSCM.getCaches(); -// caches.stream().forEach(cache -> { -// assertNotNull(cache.getLock()); -// assertThat(cache.getLock(),instanceOf(Lock.class)); -// assertNotNull(cache.getCacheFile()); -// assertThat(cache.getCacheFile(),instanceOf(File.class)); -// }); -// } - - @Test public void testGetCacheFile(){ File file = Jenkins.getInstanceOrNull().getRootDir(); @@ -121,5 +71,4 @@ public void testGetLock(){ GitMaintenanceSCM.Cache cache = new GitMaintenanceSCM.Cache(file,lock); assertNotNull(cache.getLock()); } - } From 8d72be3bbbfcaa63b93ada9d03ea3416e29b4ca2 Mon Sep 17 00:00:00 2001 From: Pc Date: Tue, 1 Aug 2023 00:30:18 +0530 Subject: [PATCH 139/146] Replace LinkedList with ArrayList --- .../plugins/git/maintenance/Logs/CacheRecord.java | 10 +++++----- .../plugins/git/maintenance/Logs/RecordList.java | 14 +++++--------- .../git/maintenance/Logs/CacheRecordTest.java | 2 +- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java index 1b54363736..8b06f4874e 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/CacheRecord.java @@ -20,7 +20,7 @@ public class CacheRecord { boolean executionStatus; long executionDuration; - Map> maintenanceData; + Map> maintenanceData; // This is to create a new Cache Record when cache is not present. @@ -91,12 +91,12 @@ public void setExecutionDuration(long executionDuration) { public void insertMaintenanceData(CacheRecord record){ if(record != null && maintenanceData != null) { - LinkedList list = maintenanceData.get(record.getMaintenanceType()); + List list = maintenanceData.get(record.getMaintenanceType()); if(list != null) { - list.addFirst(record); + list.add(0,record); // Maximum storage of 5 Maintenance Records per Cache. if (list.size() > 5) - list.removeLast(); + list.remove(list.size()-1); } } } @@ -104,7 +104,7 @@ public void insertMaintenanceData(CacheRecord record){ public List getAllMaintenanceRecordsForSingleCache(){ List maintenanceData = new ArrayList<>(); - for(Map.Entry> entry : this.maintenanceData.entrySet()){ + for(Map.Entry> entry : this.maintenanceData.entrySet()){ maintenanceData.addAll(entry.getValue()); } diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java index 8e5ae3728d..a591fa3f8c 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/RecordList.java @@ -1,22 +1,18 @@ package jenkins.plugins.git.maintenance.Logs; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; +import java.util.*; public class RecordList { - LinkedList maintenanceRecords; + List maintenanceRecords; Set cacheSet; public RecordList(){ - maintenanceRecords = new LinkedList<>(); + maintenanceRecords = new ArrayList<>(); cacheSet = new HashSet<>(); } List getMaintenanceRecords(){ - return new LinkedList<>(maintenanceRecords); + return new ArrayList<>(maintenanceRecords); } void addRecord(CacheRecord cacheRecord){ @@ -54,7 +50,7 @@ record = itr.next(); } // Creates a new Cache Entry and adds the data. - maintenanceRecords.addFirst(cacheRecord); + maintenanceRecords.add(0,cacheRecord); cacheSet.add(repoName); } diff --git a/src/test/java/jenkins/plugins/git/maintenance/Logs/CacheRecordTest.java b/src/test/java/jenkins/plugins/git/maintenance/Logs/CacheRecordTest.java index e09c9b8a4c..0fd27320d9 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/Logs/CacheRecordTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/Logs/CacheRecordTest.java @@ -82,7 +82,7 @@ public void testInsertMaintenanceData(){ record.insertMaintenanceData(incrementalRepackRecord); record.insertMaintenanceData(looseObjectsRecord); - for(Map.Entry> entry : record.maintenanceData.entrySet()){ + for(Map.Entry> entry : record.maintenanceData.entrySet()){ assertEquals(1,entry.getValue().size()); } } From 3c3a39c194f528ad1da37bd7fe9ed2e33f95b624 Mon Sep 17 00:00:00 2001 From: Hrushi20 Date: Sat, 28 Oct 2023 03:51:22 +0530 Subject: [PATCH 140/146] attempt to fix incremental-repack test Signed-off-by: Hrushi20 --- .../plugins/git/maintenance/TaskExecutorTest.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java index 5926c702c6..249dddf541 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskExecutorTest.java @@ -39,7 +39,7 @@ public class TaskExecutorTest extends AbstractGitRepository { private Task gitTask; - public TaskExecutorTest(TaskType taskType) { + public TaskExecutorTest(TaskType taskType){ this.gitTask = new Task(taskType); this.gitTask.setCronSyntax("* * * * *"); this.gitTask.setIsTaskConfigured(true); @@ -65,7 +65,6 @@ public void testGitClient(){ assertTrue(taskExecutor.getCaches().size() > 0); GitMaintenanceSCM.Cache cache = taskExecutor.getCaches().get(0); File cacheFile = cache.getCacheFile(); - assertNotNull(taskExecutor.getGitClient(cacheFile)); assertThat(taskExecutor.getGitClient(cacheFile),instanceOf(GitClient.class)); } @@ -83,7 +82,11 @@ public void testGetCaches(){ } @Test - public void testExecuteGitMaintenance() throws InterruptedException { + public void testExecuteGitMaintenance() throws Exception { + + // This will create a pack file, incremental repack will then start to work. + repo.git("repack"); + TaskExecutor taskExecutor = new TestTaskExecutorHelper(gitTask,testGitDir); GitMaintenanceSCM.Cache cache = taskExecutor.getCaches().get(0); File cacheFile = cache.getCacheFile(); @@ -96,7 +99,11 @@ public void testExecuteGitMaintenance() throws InterruptedException { } @Test - public void testRunnable() { + public void testRunnable() throws Exception { + + // This will create a pack file, incremental repack will then start to work. + repo.git("repack"); + MaintenanceTaskConfiguration config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); config.setIsGitMaintenanceRunning(true); config.setCronSyntax(gitTask.getTaskType(),"* * * * *"); From 026aa92f0dc3c45739a5e24c36a6da07062e17d1 Mon Sep 17 00:00:00 2001 From: Hrushi20 Date: Sat, 28 Oct 2023 04:37:45 +0530 Subject: [PATCH 141/146] extend lifetime of execution thread unit test Signed-off-by: Hrushi20 --- .../jenkins/plugins/git/maintenance/TaskSchedulerTest.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java index 92b6024475..1b9937fe3c 100644 --- a/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java +++ b/src/test/java/jenkins/plugins/git/maintenance/TaskSchedulerTest.java @@ -117,6 +117,12 @@ public void testCreateExecutionThread(){ config.setCronSyntax(TaskType.PREFETCH,"* * * * *"); config.setIsTaskConfigured(TaskType.PREFETCH,true); + config.setCronSyntax(TaskType.LOOSE_OBJECTS,"* * * * *"); + config.setIsTaskConfigured(TaskType.LOOSE_OBJECTS,true); + config.setCronSyntax(TaskType.COMMIT_GRAPH,"* * * * *"); + config.setIsTaskConfigured(TaskType.COMMIT_GRAPH,true); + config.setCronSyntax(TaskType.GC,"* * * * *"); + config.setIsTaskConfigured(TaskType.GC,true); List maintenanceTasks = config.getMaintenanceTasks(); taskScheduler.addTasksToQueue(maintenanceTasks); From e266d16696eb6b2def976643e57be29ad1423de2 Mon Sep 17 00:00:00 2001 From: Hrushi20 Date: Sat, 28 Oct 2023 05:36:45 +0530 Subject: [PATCH 142/146] Fixed spotbug issue, update pom.xml Signed-off-by: Hrushi20 --- pom.xml | 1 - src/main/java/jenkins/plugins/git/maintenance/Cron.java | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 9a8eec5cf1..62bc3d3e4b 100644 --- a/pom.xml +++ b/pom.xml @@ -102,7 +102,6 @@ org.jenkins-ci.plugins git-client - 3.12.0 org.jenkins-ci.plugins diff --git a/src/main/java/jenkins/plugins/git/maintenance/Cron.java b/src/main/java/jenkins/plugins/git/maintenance/Cron.java index d45e9e4dda..889dc6d340 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Cron.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Cron.java @@ -13,7 +13,7 @@ public class Cron extends PeriodicWork { @Override public long getInitialDelay(){ - return MIN - (Calendar.getInstance().get(Calendar.SECOND) * 1000); + return MIN - (Calendar.getInstance().get(Calendar.SECOND) * 1000L); } @Override From c0ff1281455f2dfa67a1b826c1bd9bda8d2768a8 Mon Sep 17 00:00:00 2001 From: Hrushi20 Date: Sat, 28 Oct 2023 13:59:50 +0530 Subject: [PATCH 143/146] Fix javadoc error Signed-off-by: Hrushi20 --- .../java/jenkins/plugins/git/maintenance/TaskScheduler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java index ff5781421d..cf0999ee23 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java +++ b/src/main/java/jenkins/plugins/git/maintenance/TaskScheduler.java @@ -16,7 +16,7 @@ import java.util.logging.Logger; /** - * TaskScheduler is responsible for scheduling maintenance tasks. It validates if a task is configured & verifies cron syntax before scheduling. + * TaskScheduler is responsible for scheduling maintenance tasks. It validates if a task is configured and verifies cron syntax before scheduling. * TaskScheduler acts as a producer by adding the appropriate task into a maintenance queue. * * @author Hrushikesh Rao From a28e3312811d19ec1df93b25071d883b55f60b3a Mon Sep 17 00:00:00 2001 From: Hrushi20 Date: Thu, 13 Feb 2025 01:34:44 +0530 Subject: [PATCH 144/146] Fix unwanted todo comment Signed-off-by: Hrushi20 --- .../java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java | 1 - .../plugins/git/maintenance/MaintenanceTaskConfiguration.java | 1 - src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java | 1 - src/main/java/jenkins/plugins/git/maintenance/Task.java | 1 - 4 files changed, 4 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java b/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java index acd22c3a72..04ba3ef65a 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Logs/XmlSerialize.java @@ -28,7 +28,6 @@ public class XmlSerialize{ public XmlSerialize(){ this.xStream = new XStream(new DomDriver()); - // Need to change the Permission type. Todo need to read documentation and update security. this.xStream.addPermission(AnyTypePermission.ANY); Jenkins jenkins = Jenkins.getInstanceOrNull(); diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java index 573a0cbaf3..0cb2b25500 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceTaskConfiguration.java @@ -27,7 +27,6 @@ /** * MaintenanceTaskConfiguration is responsible for creating tasks,fetching tasks, storing the configuration in Jenkins. It extends the * {@link GlobalConfiguration} class. - * @since TODO * * @author Hrushikesh Rao */ diff --git a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java index d258ede50e..746c451060 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java +++ b/src/main/java/jenkins/plugins/git/maintenance/MaintenanceUI.java @@ -106,7 +106,6 @@ public void doExecuteMaintenanceTask(StaplerRequest req, StaplerResponse res) th MaintenanceTaskConfiguration config = GlobalConfiguration.all().get(MaintenanceTaskConfiguration.class); if(config != null) { - // Todo // schedule maintenance tasks only if all cron syntax are valid. // else can't schedule maintenance tasks. diff --git a/src/main/java/jenkins/plugins/git/maintenance/Task.java b/src/main/java/jenkins/plugins/git/maintenance/Task.java index 389c030c07..06168b59d9 100644 --- a/src/main/java/jenkins/plugins/git/maintenance/Task.java +++ b/src/main/java/jenkins/plugins/git/maintenance/Task.java @@ -2,7 +2,6 @@ /** * POJO to store configuration for maintenance tasks. - * @since TODO * * @author Hrushikesh Rao */ From 7ed2f81a8c6b3783d3ccff5f1e643f32a6eaff8b Mon Sep 17 00:00:00 2001 From: Hrushi20 Date: Sat, 15 Feb 2025 16:07:24 +0530 Subject: [PATCH 145/146] Trigger Build From 70ac371164be274dccc70537450f26f1fdf576d0 Mon Sep 17 00:00:00 2001 From: Hrushi20 Date: Sat, 15 Feb 2025 17:14:27 +0530 Subject: [PATCH 146/146] Add Classes to Spotbugs excludeFilter.xmwl --- src/spotbugs/excludesFilter.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/spotbugs/excludesFilter.xml b/src/spotbugs/excludesFilter.xml index bf1e7ef977..1a34e42287 100644 --- a/src/spotbugs/excludesFilter.xml +++ b/src/spotbugs/excludesFilter.xml @@ -14,6 +14,8 @@ + +