Merge "Add method for charts versioning"
diff --git a/src/com/mirantis/mcp/MCPArtifactory.groovy b/src/com/mirantis/mcp/MCPArtifactory.groovy
index 2065332..cc30f8c 100644
--- a/src/com/mirantis/mcp/MCPArtifactory.groovy
+++ b/src/com/mirantis/mcp/MCPArtifactory.groovy
@@ -110,6 +110,64 @@
 }
 
 /**
+ * Create an empty directory in Artifactory repo
+ *
+ * @param artifactoryURL String, an URL to Artifactory
+ * @param path String, a path to the desired directory including repository name
+ * @param dir String, desired directory name
+ */
+def createDir (String artifactoryURL, String path, String dir) {
+    def url = "${artifactoryURL}/${path}/${dir}/"
+    withCredentials([
+            [$class          : 'UsernamePasswordMultiBinding',
+             credentialsId   : 'artifactory',
+             passwordVariable: 'ARTIFACTORY_PASSWORD',
+             usernameVariable: 'ARTIFACTORY_LOGIN']
+    ]) {
+        sh "bash -c \"curl -X PUT -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} \'${url}\'\""
+    }
+}
+
+/**
+ * Move/copy an artifact or a folder to the specified destination
+ *
+ * @param artifactoryURL String, an URL to Artifactory
+ * @param sourcePath String, a source path to the artifact including repository name
+ * @param dstPath String, a destination path to the artifact including repository name
+ * @param copy boolean, whether to copy or move the item, default is move
+ * @param dryRun boolean, whether to perform dry run on not, default is false
+ */
+def moveItem (String artifactoryURL, String sourcePath, String dstPath, boolean copy = false, boolean dryRun = false) {
+    def url = "${artifactoryURL}/api/${copy ? 'copy' : 'move'}/${sourcePath}?to=/${dstPath}&dry=${dryRun ? '1' : '0'}"
+    withCredentials([
+            [$class          : 'UsernamePasswordMultiBinding',
+             credentialsId   : 'artifactory',
+             passwordVariable: 'ARTIFACTORY_PASSWORD',
+             usernameVariable: 'ARTIFACTORY_LOGIN']
+    ]) {
+        sh "bash -c \"curl -X POST -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} \'${url}\'\""
+    }
+}
+
+/**
+ * Recursively delete the specified artifact or a folder
+ *
+ * @param artifactoryURL String, an URL to Artifactory
+ * @param itemPath String, a source path to the item including repository name
+ */
+def deleteItem (String artifactoryURL, String itemPath) {
+    def url = "${artifactoryURL}/${itemPath}"
+    withCredentials([
+            [$class          : 'UsernamePasswordMultiBinding',
+             credentialsId   : 'artifactory',
+             passwordVariable: 'ARTIFACTORY_PASSWORD',
+             usernameVariable: 'ARTIFACTORY_LOGIN']
+    ]) {
+        sh "bash -c \"curl -X DELETE -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} \'${url}\'\""
+    }
+}
+
+/**
  * Get properties for specified artifact in Artifactory
  * Returns LinkedHashMap of properties
  *
diff --git a/src/com/mirantis/mk/Common.groovy b/src/com/mirantis/mk/Common.groovy
index c0059bb..8eee149 100644
--- a/src/com/mirantis/mk/Common.groovy
+++ b/src/com/mirantis/mk/Common.groovy
@@ -1023,3 +1023,14 @@
     Random rand = new Random(System.currentTimeMillis())
     return (1..n).collect { pool[rand.nextInt(pool.size())] }.join()
 }
+
+/**
+ * Checks whether string is semver complaint version
+ * @param string version
+*/
+
+def isSemVer(version){
+    // Official regex for Semver2 (https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string)
+    String semVerRegex = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
+    return version ==~ semVerRegex
+}
\ No newline at end of file
diff --git a/src/com/mirantis/mk/Git.groovy b/src/com/mirantis/mk/Git.groovy
index 9195c9b..94eb55b 100644
--- a/src/com/mirantis/mk/Git.groovy
+++ b/src/com/mirantis/mk/Git.groovy
@@ -473,3 +473,51 @@
 
     return commitMessage
 }
+
+/**
+ * Update (or create if cannot find) gerrit change request
+ *
+ * @param params   Map of parameters to customize commit
+ *   - gerritAuth         A map containing information about Gerrit. Should include HOST, PORT and USER
+ *   - credentialsId      Jenkins credentials id for gerrit
+ *   - repo               Local directory with repository
+ *   - comment            Commit comment
+ *   - change_id_seed     Custom part of change id which can be added during change id generation
+ *   - branch             Name of the branch for uploading
+ *   - topic              Topic of the change
+ *   - project            Gerrit project to search in for gerrit change request
+ *   - status             Change request's status to search for
+ *   - changeAuthorEmail  Author's email of the change
+ *   - changeAuthorName   Author's name of the change
+ */
+def updateChangeRequest(Map params) {
+    def gerrit = new com.mirantis.mk.Gerrit()
+
+    def commitMessage
+    def auth = params['gerritAuth']
+    def creds = params['credentialsId']
+    def repo = params['repo']
+    def comment = params['comment']
+    def change_id_seed = params.get('change_id_seed', JOB_NAME)
+    def branch = params['branch']
+    def topic = params['topic']
+    def project = params['project']
+    def status = params.get('status', 'open')
+    def changeAuthorEmail = params['changeAuthorEmail']
+    def changeAuthorName = params['changeAuthorName']
+
+    def changeParams = ['owner': auth['USER'], 'status': status, 'project': project, 'branch': branch, 'topic': topic]
+    def gerritChange = gerrit.findGerritChange(creds, auth, changeParams)
+    def changeId
+    def commit
+    if (gerritChange) {
+        def jsonChange = readJSON text: gerritChange
+        changeId = jsonChange['id']
+    }
+    commitMessage = genCommitMessage(repo, comment, changeId, change_id_seed)
+    commitGitChanges(repo, commitMessage, changeAuthorEmail, changeAuthorName, false, false)
+    dir(repo){
+        commit = getGitCommit()
+    }
+    pushForReview(repo, creds, commit, branch, topic)
+}