From 359caa504461de0855eb2e777b1f226a623378ab Mon Sep 17 00:00:00 2001 From: Mat V Date: Fri, 4 Jun 2021 22:39:37 +0200 Subject: [PATCH 1/6] =?UTF-8?q?=F0=9F=93=9D=20Write=20scripts=20output=20i?= =?UTF-8?q?n=20log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/fr/yodamad/svn2git/io/Shell.kt | 7 ++++--- src/main/kotlin/fr/yodamad/svn2git/service/GitManager.kt | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/fr/yodamad/svn2git/io/Shell.kt b/src/main/kotlin/fr/yodamad/svn2git/io/Shell.kt index b15842b..eff5653 100644 --- a/src/main/kotlin/fr/yodamad/svn2git/io/Shell.kt +++ b/src/main/kotlin/fr/yodamad/svn2git/io/Shell.kt @@ -4,6 +4,7 @@ import fr.yodamad.svn2git.domain.Migration import fr.yodamad.svn2git.service.util.CommandManager import org.apache.commons.io.IOUtils import org.slf4j.LoggerFactory +import org.springframework.util.StringUtils.isEmpty import java.io.* import java.nio.charset.Charset import java.time.LocalDateTime @@ -65,7 +66,7 @@ object Shell { */ @JvmOverloads @Throws(InterruptedException::class, IOException::class) - fun execCommand(commandManager: CommandManager, directory: String, command: String?, securedCommandToPrint: String? = command, usePowershell: Boolean = false): Int { + fun execCommand(commandManager: CommandManager, directory: String, command: String?, securedCommandToPrint: String? = command, usePowershell: Boolean = false, alwaysPrintOutput: Boolean = false): Int { val builder = ProcessBuilder() val execDir = formatDirectory(directory) if (isWindows) { @@ -78,9 +79,9 @@ object Shell { LOG.debug(String.format("Exec command : %s", securedCommandToPrint)) LOG.debug(String.format("in %s", execDir)) val process = builder.start() - val streamGobbler = StreamGobbler(process.inputStream) { s: String? -> LOG.debug(s) } + val streamGobbler = StreamGobbler(process.inputStream) { s: String? -> if (alwaysPrintOutput && !isEmpty(s) && !s!!.contains("password", true)) LOG.info(s) else LOG.debug(s) } Executors.newSingleThreadExecutor().submit(streamGobbler) - val errorStreamGobbler = StreamGobbler(process.errorStream) { s: String? -> LOG.debug(s) } + val errorStreamGobbler = StreamGobbler(process.errorStream) { s: String? -> LOG.error(s) } Executors.newSingleThreadExecutor().submit(errorStreamGobbler) val stderr = IOUtils.toString(process.errorStream, Charset.defaultCharset()) val exitCode = process.waitFor() diff --git a/src/main/kotlin/fr/yodamad/svn2git/service/GitManager.kt b/src/main/kotlin/fr/yodamad/svn2git/service/GitManager.kt index 0b7a96f..0337eda 100644 --- a/src/main/kotlin/fr/yodamad/svn2git/service/GitManager.kt +++ b/src/main/kotlin/fr/yodamad/svn2git/service/GitManager.kt @@ -111,7 +111,7 @@ open class GitManager(val historyMgr: HistoryManager, var cloneOK = true if (workUnit.commandManager.isFirstAttemptMigration) { try { - execCommand(workUnit.commandManager, workUnit.root, cloneCommand, safeCommand, true) + execCommand(workUnit.commandManager, workUnit.root, cloneCommand, safeCommand, true, true) } catch (thr: Throwable) { cloneOK = false LOG.warn("Cannot git svn clone", thr.message) From 74576a2d9796ec372adc9ea69f0f47390b1b297b Mon Sep 17 00:00:00 2001 From: Mat V Date: Fri, 4 Jun 2021 22:56:51 +0200 Subject: [PATCH 2/6] =?UTF-8?q?=F0=9F=9B=82=20Fix=20error=20catching=20on?= =?UTF-8?q?=20SVN=20listing=20from=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fr/yodamad/svn2git/web/rest/SvnResource.kt | 1 + .../app/migration/migration-process.service.ts | 12 ++++++++---- .../fr/yodamad/svn2git/web/rest/SvnResourceTest.java | 6 +++--- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/fr/yodamad/svn2git/web/rest/SvnResource.kt b/src/main/kotlin/fr/yodamad/svn2git/web/rest/SvnResource.kt index dc64e04..0a66e4f 100644 --- a/src/main/kotlin/fr/yodamad/svn2git/web/rest/SvnResource.kt +++ b/src/main/kotlin/fr/yodamad/svn2git/web/rest/SvnResource.kt @@ -151,6 +151,7 @@ open class SvnResource(val applicationProperties: ApplicationProperties) { } catch (ex: SVNException) { if (ex is SVNAuthenticationException) { log.error("Cannot access SVN", ex) + throw ex } else { log.warn("Flat repo", ex) } diff --git a/src/main/webapp/app/migration/migration-process.service.ts b/src/main/webapp/app/migration/migration-process.service.ts index 2156451..f656a15 100644 --- a/src/main/webapp/app/migration/migration-process.service.ts +++ b/src/main/webapp/app/migration/migration-process.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@angular/core'; import { SERVER_API_URL } from 'app/app.constants'; import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; -import { map } from 'rxjs/operators'; +import { catchError, map } from 'rxjs/operators'; import { IMigration } from 'app/shared/model/migration.model'; import { MigrationFilter } from 'app/shared/model/migration-filter.model'; @@ -56,9 +56,13 @@ export class MigrationProcessService { checkSvn(name: string, url: string, user: string, password: string, depth: number): Observable { const svnInfo = new SvnInfo(url, user, password); - return this.http - .post(`${this.repositoryUrl}/${name}?depth=${depth}`, svnInfo, { observe: 'response' }) - .pipe(map((res: EntityStructureResponseType) => res)); + return this.http.post(`${this.repositoryUrl}/${name}?depth=${depth}`, svnInfo, { observe: 'response' }).pipe( + map((res: EntityStructureResponseType) => res), + catchError(err => { + console.log(err); + throw err; + }) + ); } findActiveMigrations(): Observable { diff --git a/src/test/java/fr/yodamad/svn2git/web/rest/SvnResourceTest.java b/src/test/java/fr/yodamad/svn2git/web/rest/SvnResourceTest.java index 9a8b8d8..1587f3f 100644 --- a/src/test/java/fr/yodamad/svn2git/web/rest/SvnResourceTest.java +++ b/src/test/java/fr/yodamad/svn2git/web/rest/SvnResourceTest.java @@ -10,6 +10,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; +import org.tmatesoft.svn.core.SVNAuthenticationException; import java.util.List; @@ -127,11 +128,10 @@ public void test_svn_listing_with_depth_1() { }); } - @Test + @Test(expected = SVNAuthenticationException.class) public void test_invalid_credentials() { svnInfo.user = "hacker"; svnInfo.password = "hacker"; - SvnStructure svnStructure = svnResource.listSVN(svnInfo, Repository.simple().name, DEPTH); - assertThat(svnStructure.modules).isEmpty(); + svnResource.listSVN(svnInfo, Repository.simple().name, DEPTH); } } From 740e0fa783d0f812edecee66c5a66bd01acf644e Mon Sep 17 00:00:00 2001 From: Mat V Date: Fri, 4 Jun 2021 23:00:12 +0200 Subject: [PATCH 3/6] =?UTF-8?q?=F0=9F=92=85=20Fix=20lint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/webapp/app/migration/migration-stepper.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/app/migration/migration-stepper.component.ts b/src/main/webapp/app/migration/migration-stepper.component.ts index 846fdc1..adcdf2c 100644 --- a/src/main/webapp/app/migration/migration-stepper.component.ts +++ b/src/main/webapp/app/migration/migration-stepper.component.ts @@ -930,6 +930,6 @@ export class MigrationStepperComponent implements OnInit { } warningUploadExtension() { - return this.staticExtensions.length == 0; + return this.staticExtensions.length === 0; } } From 7a5659ade0df5abbdde3dcf3ce3009454dd1a150 Mon Sep 17 00:00:00 2001 From: Mat V Date: Sat, 5 Jun 2021 00:44:13 +0200 Subject: [PATCH 4/6] =?UTF-8?q?=F0=9F=A7=BC=20Remove=20useless=20input=20f?= =?UTF-8?q?or=20username=20for=20gitlab,=20use=20token=20one?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../svn2git/web/rest/GitlabResource.kt | 15 +++++++++ .../migration/migration-process.service.ts | 8 +++++ .../migration-stepper.component.html | 10 +++--- .../migration/migration-stepper.component.ts | 31 +++++++++++++++++-- src/main/webapp/i18n/en/migrationProcess.json | 4 ++- src/main/webapp/i18n/fr/migrationProcess.json | 4 ++- 6 files changed, 61 insertions(+), 11 deletions(-) diff --git a/src/main/kotlin/fr/yodamad/svn2git/web/rest/GitlabResource.kt b/src/main/kotlin/fr/yodamad/svn2git/web/rest/GitlabResource.kt index 3bbb00a..511f279 100644 --- a/src/main/kotlin/fr/yodamad/svn2git/web/rest/GitlabResource.kt +++ b/src/main/kotlin/fr/yodamad/svn2git/web/rest/GitlabResource.kt @@ -33,6 +33,21 @@ open class GitlabResource(val gitlabAdmin: GitlabAdmin, val logger: Logger = LoggerFactory.getLogger(GitlabResource::class.java) + /** + * @return current user for token + */ + @Timed + @PostMapping("/user") + open fun getUserFromToken(@RequestBody gitlabInfo: GitlabInfo) : ResponseEntity { + val api: UserApi = overrideGitlab(gitlabInfo).userApi + val user = api.getCurrentUser() + return if (user != null) { + ResponseEntity.ok().body(user.username) + } else { + ResponseEntity.notFound().build() + } + } + /** * Check if a user exists on Gitlab * diff --git a/src/main/webapp/app/migration/migration-process.service.ts b/src/main/webapp/app/migration/migration-process.service.ts index f656a15..4d1218f 100644 --- a/src/main/webapp/app/migration/migration-process.service.ts +++ b/src/main/webapp/app/migration/migration-process.service.ts @@ -7,6 +7,7 @@ import { IMigration } from 'app/shared/model/migration.model'; import { MigrationFilter } from 'app/shared/model/migration-filter.model'; type EntityResponseType = HttpResponse; +type StringResponseType = HttpResponse; type EntityStructureResponseType = HttpResponse; type MigrationArrayResponseType = HttpResponse; @@ -27,6 +28,13 @@ export class MigrationProcessService { constructor(private http: HttpClient) {} + currentUserFromToken(url: string, token?: string): Observable { + const gitlabInfo = new GitlabInfo(url, token); + return this.http + .post(`${this.userUrl}`, gitlabInfo, { observe: 'response', responseType: 'text' as 'json' }) + .pipe(map((res: StringResponseType) => res)); + } + checkUser(name: string, url: string, token?: string): Observable { const gitlabInfo = new GitlabInfo(url, token); return this.http diff --git a/src/main/webapp/app/migration/migration-stepper.component.html b/src/main/webapp/app/migration/migration-stepper.component.html index bb7dcf7..7e605b9 100644 --- a/src/main/webapp/app/migration/migration-stepper.component.html +++ b/src/main/webapp/app/migration/migration-stepper.component.html @@ -48,20 +48,18 @@
- + Credentials
- - - - + Account found in Gitlab diff --git a/src/main/webapp/app/migration/migration-stepper.component.ts b/src/main/webapp/app/migration/migration-stepper.component.ts index adcdf2c..d3983db 100644 --- a/src/main/webapp/app/migration/migration-stepper.component.ts +++ b/src/main/webapp/app/migration/migration-stepper.component.ts @@ -67,6 +67,7 @@ export class MigrationStepperComponent implements OnInit { svnCredsOption: string; svnDepth: number; gitlabUrl: string; + gitlabUser = ''; gitlabCredsOption: string; renamings: MigrationRenaming[] = []; artifactoryUrl: string; @@ -169,7 +170,6 @@ export class MigrationStepperComponent implements OnInit { this.nexusUrl = localStorage.getItem(NEXUS_URL); this.gitlabFormGroup = this._formBuilder.group({ - gitlabUser: ['', Validators.required], gitlabGroup: ['', Validators.required], gitlabURL: [{ value: this.gitlabUrl, disabled: true }, Validators.required], gitlabToken: [''] @@ -223,6 +223,31 @@ export class MigrationStepperComponent implements OnInit { .subscribe(res => (this.isGitlabGroupCreation = res), () => (this.isGitlabGroupCreation = false)); } + /** + * Get Gitlab user + */ + getGitlabUser() { + // initialise to true for each check + this.gitlabUserKO = null; + this.checkingGitlabUser = true; + + this._migrationProcessService + .currentUserFromToken(this.gitlabFormGroup.controls['gitlabURL'].value, this.gitlabFormGroup.controls['gitlabToken'].value) + .subscribe( + res => { + console.log(res); + this.gitlabUser = res.body; + this.gitlabUserKO = false; + this.checkingGitlabUser = false; + }, + err => { + console.log(err); + this.gitlabUserKO = true; + this.checkingGitlabUser = false; + } + ); + } + /** * Check if user exists */ @@ -260,7 +285,7 @@ export class MigrationStepperComponent implements OnInit { this._migrationProcessService .checkGroup( this.gitlabFormGroup.controls['gitlabGroup'].value, - this.gitlabFormGroup.controls['gitlabUser'].value, + this.gitlabUser, this.gitlabFormGroup.controls['gitlabURL'].value, this.gitlabFormGroup.controls['gitlabToken'].value ) @@ -451,7 +476,7 @@ export class MigrationStepperComponent implements OnInit { if (this.gitlabFormGroup.controls['gitlabToken'] !== undefined && this.gitlabFormGroup.controls['gitlabToken'].value !== '') { this.mig.gitlabToken = this.gitlabFormGroup.controls['gitlabToken'].value; } - this.mig.user = this.gitlabFormGroup.controls['gitlabUser'].value; + this.mig.user = this.gitlabUser; this.mig.gitlabGroup = this.gitlabFormGroup.controls['gitlabGroup'].value; const renaming = this.renamings.find( r => diff --git a/src/main/webapp/i18n/en/migrationProcess.json b/src/main/webapp/i18n/en/migrationProcess.json index 705924e..a63a346 100644 --- a/src/main/webapp/i18n/en/migrationProcess.json +++ b/src/main/webapp/i18n/en/migrationProcess.json @@ -6,6 +6,7 @@ "back" : " Back", "blocked": "Some namespaces aren't available. Fix before starting migration", "check" : "Check", + "check-token" : "Check Token", "checking" : "Checking", "cleaning" : { "options" : "🧹 Cleaning options", @@ -54,7 +55,7 @@ "url-help": "The base URL, e.g. https://gitlab.com/", "url-default": "Default", "url-custom": "Custom", - "credentials": "Credentials", + "username": "Username", "rename": "New name for project in Gitlab", "upload": "🦊 Upload artefacts", "use" : { @@ -62,6 +63,7 @@ }, "user" : "User", "account-found": "Account found in Gitlab", + "account-info": "{{ username }} will be use for Gitlab connection", "account-unknown": "Account not found in Gitlab you need to log in first" }, "history" : { diff --git a/src/main/webapp/i18n/fr/migrationProcess.json b/src/main/webapp/i18n/fr/migrationProcess.json index d230482..9979217 100644 --- a/src/main/webapp/i18n/fr/migrationProcess.json +++ b/src/main/webapp/i18n/fr/migrationProcess.json @@ -6,6 +6,7 @@ "back" : " Retour", "blocked": "Certains namespaces ne sont pas disponibles. Corriger pour continuer", "check" : "Vérifier", + "check-token" : "Vérifier le token", "checking" : "En cours", "cleaning" : { "options" : "🧹 Nettoyage", @@ -54,7 +55,7 @@ "url-help": "L'url de base comme https://gitlab.com/", "url-default": "Par défault", "url-custom": "Personnalisé", - "credentials": "Identifiants", + "username": "Username", "rename": "Nouveau nom du projet dans Gitlab", "upload": "🦊 Upload fichiers", "use" : { @@ -62,6 +63,7 @@ }, "user" : "Utilisateur", "account-found": "Compte trouvé sur Gitlab", + "account-info": "{{ username }} sera utilisé pour la connexion à Gitlab", "account-unknown": "Compte non trouvé sur Gitlab, vous devez vous connecter dessus au préalable" }, "history" : { From c7358bd9789072ab984c859907470a2b82174783 Mon Sep 17 00:00:00 2001 From: Mat V Date: Sat, 5 Jun 2021 00:48:01 +0200 Subject: [PATCH 5/6] =?UTF-8?q?=F0=9F=A7=B9=20Clean=20my=20mess=20after=20?= =?UTF-8?q?testing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/fr/yodamad/svn2git/e2e/FlatRepoTests.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/test/java/fr/yodamad/svn2git/e2e/FlatRepoTests.java b/src/test/java/fr/yodamad/svn2git/e2e/FlatRepoTests.java index 588a99d..0da9dc2 100644 --- a/src/test/java/fr/yodamad/svn2git/e2e/FlatRepoTests.java +++ b/src/test/java/fr/yodamad/svn2git/e2e/FlatRepoTests.java @@ -11,6 +11,7 @@ import org.gitlab4j.api.GitLabApiException; import org.gitlab4j.api.models.Branch; import org.gitlab4j.api.models.Project; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -56,6 +57,15 @@ public void cleanGitlab() throws GitLabApiException { if (project.isPresent()) api.getProjectApi().deleteProject(project.get().getId()); } + @After + public void forceCleanGitlab() throws GitLabApiException, InterruptedException { + Optional project = api.getProjectApi().getOptionalProject(flat().namespace, flat().name); + if (project.isPresent()) api.getProjectApi().deleteProject(project.get().getId()); + while(api.getProjectApi().getOptionalProject(flat().namespace, flat().name).isPresent()) { + Thread.sleep(500); + } + } + @Test public void test_migration_on_flat_repository() throws ExecutionException, InterruptedException, GitLabApiException { Migration migration = initFlatMigration(applicationProperties); From 474e8f27a8051530614706ed84b9477a4000ae6d Mon Sep 17 00:00:00 2001 From: Mat V Date: Sat, 5 Jun 2021 00:56:09 +0200 Subject: [PATCH 6/6] =?UTF-8?q?=F0=9F=95=BA=20Release=202.2.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9a4d27c..07c863b 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ fr.yodamad.svn2git svn-2-git - 2.2.0 + 2.2.1 jar Svn 2 GitLab