Skip to content

Commit 53be9bb

Browse files
authored
📣 Release 2.3.0
2 parents 50a0ed3 + eba9fed commit 53be9bb

File tree

14 files changed

+78
-28
lines changed

14 files changed

+78
-28
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ But it is also available from 🐳 [Docker Hub](https://hub.docker.com/repositor
1313
docker run --name svn2git -v /tmp/svn2git:/svn2git -p 8080:8080 yodamad/svn2git:latest
1414
```
1515

16+
### ⚠️ **For Windows OS users** ⚠️
17+
18+
Due to Windows OS mess *#troll*, it is highly recommended to either use docker image 🐳 or use [WSL2](https://docs.microsoft.com/fr-fr/windows/wsl/install) usage rather than directly launching through cmd or powershell
19+
1620
## ✨ Some quick tips to help you with the tool
1721

1822
💪 If you have large repositories to migrate, you may need to ↗️ JVM size :

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<groupId>fr.yodamad.svn2git</groupId>
66
<artifactId>svn-2-git</artifactId>
7-
<version>2.2.3</version>
7+
<version>2.3.0</version>
88
<packaging>jar</packaging>
99
<name>Svn 2 GitLab</name>
1010

src/main/kotlin/fr/yodamad/svn2git/functions/StringFunctions.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,5 @@ fun String.decode(): String = decode(this, "UTF-8")
1919
fun String.gitFormat(): String = this.decode().replace(" ", "_")
2020

2121
fun String.escape(): String = if (isWindows) this else this.replace("\\", "\\\\").replace("$", """\$""")
22+
23+
fun String.escapeParenthesis(): String = this.replace("(", "\\(").replace(")", "\\)")

src/main/kotlin/fr/yodamad/svn2git/service/Cleaner.kt

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import fr.yodamad.svn2git.domain.enumeration.StatusEnum.DONE_WITH_WARNINGS
1313
import fr.yodamad.svn2git.domain.enumeration.StepEnum
1414
import fr.yodamad.svn2git.domain.enumeration.StepEnum.*
1515
import fr.yodamad.svn2git.domain.enumeration.SvnLayout
16+
import fr.yodamad.svn2git.domain.enumeration.SvnLayout.TAG
1617
import fr.yodamad.svn2git.functions.*
1718
import fr.yodamad.svn2git.io.Shell
1819
import fr.yodamad.svn2git.io.Shell.execCommand
@@ -75,7 +76,7 @@ open class Cleaner(val historyMgr: HistoryManager,
7576
branchName = branchName.replaceFirst("origin/".toRegex(), "")
7677
LOG.debug("Branch $branchName", branchName)
7778
// checkout new branchName from existing remote branch
78-
val gitCommand = String.format("git checkout -b %s %s", branchName, b)
79+
val gitCommand = String.format("git checkout -b \"%s\" \"%s\"", branchName, b)
7980
execCommand(workUnit.commandManager, workUnit.directory, gitCommand)
8081
// listCleanedFilesInSvnLocation
8182
val cleanedFilesBranch: CleanedFiles = listCleanedFilesInSvnLocation(workUnit, b.replace("origin", "branches"), SvnLayout.BRANCH)
@@ -97,10 +98,10 @@ open class Cleaner(val historyMgr: HistoryManager,
9798
Consumer { t: String ->
9899
try {
99100
// checkout new branch 'tmp_tag' from existing tag
100-
val gitCommand = String.format("git checkout -b tmp_tag %s", t)
101+
val gitCommand = String.format("git checkout -b tmp_tag \"%s\"", t)
101102
execCommand(workUnit.commandManager, workUnit.directory, gitCommand)
102103
// listCleanedFilesInSvnLocation
103-
val cleanedFilesTag: CleanedFiles = listCleanedFilesInSvnLocation(workUnit, t.replace("origin", "tags"), SvnLayout.TAG)
104+
val cleanedFilesTag: CleanedFiles = listCleanedFilesInSvnLocation(workUnit, t.replace("origin", "tags"), TAG)
104105
cleanedFilesMap[t.replace("origin", "tags")] = cleanedFilesTag
105106
// back to master
106107
execCommand(workUnit.commandManager, workUnit.directory, checkout())
@@ -293,7 +294,6 @@ open class Cleaner(val historyMgr: HistoryManager,
293294
open fun cleanForbiddenExtensions(workUnit: WorkUnit): Boolean {
294295
var clean = false
295296
if (!StringUtils.isEmpty(workUnit.migration.forbiddenFileExtensions)) {
296-
297297
// needed?
298298
execCommand(workUnit.commandManager, workUnit.directory, gc())
299299

@@ -418,15 +418,15 @@ open class Cleaner(val historyMgr: HistoryManager,
418418
val gitElementsToDelete: MutableList<String> = if (isTags) {
419419
Files.readAllLines(Paths.get(workUnit.directory, GIT_LIST))
420420
.stream()
421-
.map { l: String -> l.trim { it <= ' ' }.replace("origin/", "") }
421+
.map { l: String -> l.trim { it <= ' ' }.replace("origin/", "").decode().encode() }
422422
.filter { t: String -> t.startsWith("tags") }
423423
.map { l: String -> l.replace(TAGS, "") }
424424
.filter { l: String -> !l.equals(workUnit.migration.trunk, ignoreCase = true) }
425425
.collect(Collectors.toList())
426426
} else {
427427
Files.readAllLines(Paths.get(workUnit.directory, GIT_LIST))
428428
.stream()
429-
.map { l: String -> l.trim { it <= ' ' }.replace("origin/", "") }
429+
.map { l: String -> l.trim { it <= ' ' }.replace("origin/", "").decode().encode() }
430430
.filter { l: String -> !l.startsWith(TAGS) }
431431
.filter { l: String -> !l.equals(workUnit.migration.trunk, ignoreCase = true) }
432432
.collect(Collectors.toList())
@@ -480,12 +480,14 @@ open class Cleaner(val historyMgr: HistoryManager,
480480
// Remove none git branches
481481
gitElementsToDelete.forEach(Consumer { line: String ->
482482
try {
483-
var cleanCmd = String.format("git branch -d -r origin/%s", String.format("%s%s", if (isTags) TAGS else "", line))
483+
var cleanCmd = String.format("git branch -d -r origin/%s", String.format("\"%s%s\"", if (isTags) TAGS else "", line))
484484
execCommand(workUnit.commandManager, workUnit.directory, cleanCmd)
485485
cleanCmd = if (Shell.isWindows) {
486486
String.format("rd /s /q \".git\\svn\\refs\\remotes\\origin\\%s\\\"", String.format("%s%s", if (isTags) "tags\\" else "", line))
487487
} else {
488-
String.format("rm -rf .git/svn/refs/remotes/origin/%s", String.format("%s%s", if (isTags) TAGS else "", line))
488+
// var mutableLine = line
489+
// if (line.contains("(")) mutableLine = line.escapeParenthesis()
490+
String.format("rm -rf .git/svn/refs/remotes/origin/%s", String.format("\"%s%s\"", if (isTags) TAGS else "", line))
489491
}
490492
execCommand(workUnit.commandManager, workUnit.directory, cleanCmd)
491493
} catch (ex: IOException) {

src/main/kotlin/fr/yodamad/svn2git/service/GitManager.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ open class GitManager(val historyMgr: HistoryManager,
233233
// will have no parents and it will be the root of a new history totally disconnected from all the
234234
// other branches and commits
235235
execCommand(workUnit.commandManager, workUnit.directory,
236-
gitCommand(CHECKOUT, "--orphan", "TEMP_BRANCH_$branch"))
236+
gitCommand(CHECKOUT, "--orphan", "\"TEMP_BRANCH_$branch\""))
237237

238238
// Stage All (new, modified, deleted) files. Equivalent to git add . (in Git Version 2.x)
239239
execCommand(workUnit.commandManager, workUnit.directory, gitCommand("add", flags = "-A"))
@@ -264,7 +264,7 @@ open class GitManager(val historyMgr: HistoryManager,
264264
// create the remote
265265
addRemote(workUnit, true)
266266
// push to remote
267-
execCommand(workUnit.commandManager, workUnit.directory, gitCommand("push", "-f", "origin $branch"))
267+
execCommand(workUnit.commandManager, workUnit.directory, gitCommand("push", "-f", "origin \"$branch\""))
268268
historyMgr.endStep(history, StatusEnum.DONE, "Push $branch with no history")
269269
}
270270
} catch (gitEx: IOException) {

src/main/kotlin/fr/yodamad/svn2git/service/util/GitBranchManager.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ open class GitBranchManager(val gitManager: GitManager,
4343
}
4444

4545
try {
46-
execCommand(workUnit.commandManager, workUnit.directory, "git checkout -b \"$branchName\" $branch")
46+
execCommand(workUnit.commandManager, workUnit.directory, "git checkout -b \"$branchName\" \"$branch\"")
4747
} catch (iEx: IOException) {
4848
LOG.error(FAILED_TO_PUSH_BRANCH, iEx)
4949
historyMgr.endStep(history, StatusEnum.FAILED, iEx.message)
@@ -56,7 +56,7 @@ open class GitBranchManager(val gitManager: GitManager,
5656
if (workUnit.migration.svnHistory == "all") {
5757
try {
5858
gitManager.addRemote(workUnit, true)
59-
execCommand(workUnit.commandManager, workUnit.directory, "$GIT_PUSH --set-upstream origin $branchName")
59+
execCommand(workUnit.commandManager, workUnit.directory, "$GIT_PUSH --set-upstream origin \"$branchName\"")
6060
historyMgr.endStep(history, StatusEnum.DONE)
6161
} catch (iEx: IOException) {
6262
LOG.error(FAILED_TO_PUSH_BRANCH, iEx)

src/main/kotlin/fr/yodamad/svn2git/service/util/GitCommands.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ const val MASTER = "master"
1919
fun gitCommand(command: String, flags: String? = "", target: String? = "") = "git $command $flags $target"
2020

2121
// Branch management
22-
fun deleteBranch(branch: String) = gitCommand(BRANCH, "-D", branch)
23-
fun renameBranch(branch: String) = gitCommand(BRANCH, "-m", branch)
22+
fun deleteBranch(branch: String) = gitCommand(BRANCH, "-D", "\"$branch\"")
23+
fun renameBranch(branch: String) = gitCommand(BRANCH, "-m", "\"$branch\"")
2424

2525
// Pull management
2626
fun checkoutFromOrigin(branch: String) = gitCommand(CHECKOUT, "-b", "${branch.gitFormat()} refs/remotes/origin/${branch.encode()}")

src/main/kotlin/fr/yodamad/svn2git/service/util/GitTagManager.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,10 @@ open class GitTagManager(val gitManager: GitManager,
5353
val noHistory = workUnit.migration.svnHistory != "all"
5454

5555
// checkout a new branch using local tagName and remote tag name
56-
execCommand(workUnit.commandManager, workUnit.directory, "git checkout -b tmp_tag $tag")
56+
execCommand(workUnit.commandManager, workUnit.directory, "git checkout -b tmp_tag \"$tag\"")
5757

5858
// If this tag does not contain any files we will ignore it and add warning to logs.
5959
if (!isFileInFolder(workUnit.directory)) {
60-
6160
// Switch over to master
6261
execCommand(workUnit.commandManager, workUnit.directory, "git checkout master")
6362

@@ -75,14 +74,14 @@ open class GitTagManager(val gitManager: GitManager,
7574
execCommand(workUnit.commandManager, workUnit.directory, "git checkout master")
7675

7776
// create tag from tmp_tag branch.
78-
execCommand(workUnit.commandManager, workUnit.directory, "git tag $tagName tmp_tag")
77+
execCommand(workUnit.commandManager, workUnit.directory, "git tag \"$tagName\" tmp_tag")
7978

8079
// add remote to master
8180
gitManager.addRemote(workUnit, false)
8281

8382
// push the tag to remote
8483
// crashes if branch with same name so prefixing with refs/tags/
85-
execCommand(workUnit.commandManager, workUnit.directory, "git push -u origin refs/tags/$tagName")
84+
execCommand(workUnit.commandManager, workUnit.directory, "git push -u origin \"refs/tags/$tagName\"")
8685

8786
// delete the tmp_tag branch now that the tag has been created.
8887
execCommand(workUnit.commandManager, workUnit.directory, "git branch -D tmp_tag")

src/main/kotlin/fr/yodamad/svn2git/web/rest/SvnResource.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ open class SvnResource(val applicationProperties: ApplicationProperties) {
118118
val modulesFounds: MutableList<SvnModule> = ArrayList()
119119
list.receiver = ISvnObjectReceiver { _, `object`: SVNDirEntry ->
120120
val name = `object`.relativePath
121-
if (name != null && !name.isEmpty() && !keywords().contains(name)) {
121+
if (name != null && !name.isEmpty() && !keywords().contains(name) && module?.layoutElements.isNullOrEmpty()) {
122122

123123
// found a directory
124124
if (`object`.kind == SVNNodeKind.DIR) {
@@ -140,6 +140,8 @@ open class SvnResource(val applicationProperties: ApplicationProperties) {
140140
if (module != null) {
141141
log.info(String.format("Module %s with layout %s", module.name, name))
142142
module.layoutElements.add(name)
143+
module.flat = false
144+
modulesFounds.clear()
143145
} else {
144146
// Root level case
145147
modulesFounds.add(FakeModule())
@@ -159,7 +161,7 @@ open class SvnResource(val applicationProperties: ApplicationProperties) {
159161
modulesFounds.stream()
160162
.filter { m: SvnModule? -> m !is FakeModule }
161163
.map { e: SvnModule -> modules.add(e) }.count()
162-
if (!modules.isEmpty()) {
164+
if (modules.isNotEmpty()) {
163165
modules.forEach(
164166
Consumer { svnSubMod: SvnModule ->
165167
svnSubMod.subModules.addAll(

src/main/resources/templates/scripts/git-svn-clone.sh.hbs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ proc gitSvnClone { user password } {
1616
exp_continue
1717
}
1818

19+
-gl "APR does not understand this error code*" {
20+
puts "catching error... continue with git svn fetch"
21+
return 1
22+
}
23+
eof { return 0 }
1924

2025
-gl "couldn't truncate file*" {
2126
puts "catching error... continue with git svn fetch"

0 commit comments

Comments
 (0)