Skip to content

Commit e670ca4

Browse files
authored
Fix issue encoding hash character when used in a file name (#175)
Using `URI(protocol, null, host, port, path, query, ref)` encodes the path correctly except for the `#` character which is confusing. The fragment is sent in the `ref` argument, so it should know to escape it. Switch to the encoder provided in `com.google.common.net` and encode the substitutions manually.
1 parent 8dc9022 commit e670ca4

File tree

5 files changed

+38
-18
lines changed

5 files changed

+38
-18
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
- Add images to README
88
- Add Open Collective link to README
9+
- Fix issue where the '#' character in a file name is not correctly encoded.
910

1011
## [4.0.1]
1112
- Fixed settings button opening the wrong menu.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package uk.co.ben_gibson.git.link.url
2+
3+
import com.google.common.net.UrlEscapers
4+
5+
fun encode(value: String): String = UrlEscapers.urlPathSegmentEscaper().escape(value)

src/main/kotlin/uk/co/ben_gibson/git/link/url/UrlExtensions.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,22 @@ fun URL.toHttps(): URL {
1515
}
1616

1717
return URL("https", host, port, normalised)
18+
}
19+
20+
fun URL.trimPath(): URL {
21+
if (!path.endsWith("/")) {
22+
return this;
23+
}
24+
25+
var normalisedFile = path.trimEnd('/')
26+
27+
query?.let {
28+
normalisedFile = normalisedFile.plus("?${query}")
29+
}
30+
31+
ref?.let {
32+
normalisedFile = normalisedFile.plus("#${ref}")
33+
}
34+
35+
return URL(protocol, host, port, normalisedFile)
1836
}

src/main/kotlin/uk/co/ben_gibson/git/link/url/factory/TemplatedUrlFactory.kt

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@ import uk.co.ben_gibson.git.link.git.File
55
import uk.co.ben_gibson.git.link.ui.LineSelection
66
import uk.co.ben_gibson.git.link.url.*
77
import uk.co.ben_gibson.git.link.url.template.UrlTemplates
8-
import java.net.URI
98
import java.net.URL
109
import java.util.regex.Pattern
1110

12-
1311
class TemplatedUrlFactory(private val templates: UrlTemplates) : UrlFactory {
1412
private val remotePathPattern = Pattern.compile("\\{remote:url:path:(\\d)}")
1513

@@ -22,20 +20,9 @@ class TemplatedUrlFactory(private val templates: UrlTemplates) : UrlFactory {
2220

2321
processTemplate = processBaseUrl(processTemplate, options.baseUrl)
2422
processTemplate = removeUnmatchedSubstitutions(processTemplate)
23+
processTemplate = processTemplate.replace("(?<!:)/{2,}".toRegex(), "/")
2524

26-
val url = URL(processTemplate)
27-
28-
val uri = URI(
29-
url.protocol,
30-
null,
31-
url.host,
32-
url.port,
33-
url.path.replace("/{2,}".toRegex(), "/").trimEnd('/'),
34-
url.query,
35-
url.ref
36-
);
37-
38-
return URL(uri.toASCIIString())
25+
return URL(processTemplate).trimPath()
3926
}
4027

4128
private fun removeUnmatchedSubstitutions(template: String) = template.replace("\\{.+?}".toRegex(), "")
@@ -87,12 +74,12 @@ class TemplatedUrlFactory(private val templates: UrlTemplates) : UrlFactory {
8774
}
8875

8976
private fun processBranch(template: String, branch: String) = template
90-
.replace("{branch}", branch)
77+
.replace("{branch}", encode(branch))
9178

9279
private fun processFile(template: String, file: File) = template
9380
.replace("{object}", if (file.isDirectory) "tree" else "blob")
94-
.replace("{file:name}", if (file.isRoot) "" else file.name)
95-
.replace("{file:path}", file.path)
81+
.replace("{file:name}", if (file.isRoot) "" else encode(file.name))
82+
.replace("{file:path}", file.path.split("/").map { encode(it) }.joinToString("/"))
9683

9784
private fun processCommit(template: String, commit: Commit) = template
9885
.replace("{commit}", commit.toString())

src/test/kotlin/uk/co/ben_gibson/git/link/GitLabTest.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,15 @@ class GitLabTest {
4040
UrlOptionsFileAtCommit(REMOTE_BASE_URL, FILE, COMMIT, LineSelection(10, 20)),
4141
"https://gitlab.com/my/repo/blob/b032a0707beac9a2f24b1b7d97ee4f7156de182c/src/Foo.java#L10-20"
4242
),
43+
Arguments.of(
44+
UrlOptionsFileAtBranch(
45+
REMOTE_BASE_URL,
46+
File("Code.cs", false, "Assets/#/Sources", false),
47+
BRANCH,
48+
LINE_SELECTION
49+
),
50+
"https://gitlab.com/my/repo/blob/master/Assets/%23/Sources/Code.cs#L10-20"
51+
),
4352
Arguments.of(
4453
UrlOptionsFileAtCommit(
4554
REMOTE_BASE_URL,

0 commit comments

Comments
 (0)