21
21
package com .spotify .github .v3 .repos ;
22
22
23
23
import com .fasterxml .jackson .annotation .JsonProperty ;
24
+ import com .fasterxml .jackson .core .JsonParser ;
25
+ import com .fasterxml .jackson .databind .DeserializationContext ;
26
+ import com .fasterxml .jackson .databind .JsonDeserializer ;
27
+ import com .fasterxml .jackson .databind .JsonNode ;
24
28
import com .fasterxml .jackson .databind .annotation .JsonDeserialize ;
25
29
import com .fasterxml .jackson .databind .annotation .JsonSerialize ;
26
30
import com .spotify .github .GithubStyle ;
31
+ import com .spotify .github .v3 .git .ImmutableShaLink ;
27
32
import com .spotify .github .v3 .git .ShaLink ;
33
+ import java .io .IOException ;
28
34
import java .net .URI ;
35
+ import java .net .URISyntaxException ;
36
+ import java .net .URLEncoder ;
37
+ import java .nio .charset .StandardCharsets ;
29
38
import java .util .Optional ;
30
39
import javax .annotation .Nullable ;
31
40
import org .immutables .value .Value ;
34
43
@ Value .Immutable
35
44
@ GithubStyle
36
45
@ JsonSerialize (as = ImmutableBranch .class )
37
- @ JsonDeserialize (as = ImmutableBranch .class )
46
+ @ JsonDeserialize (as = ImmutableBranch .class , using = BranchDeserializer . class )
38
47
public interface Branch {
39
48
40
49
/** Branch name */
@@ -52,3 +61,46 @@ public interface Branch {
52
61
/** Branch protection API URL */
53
62
Optional <URI > protectionUrl ();
54
63
}
64
+
65
+ class BranchDeserializer extends JsonDeserializer <ImmutableBranch > {
66
+
67
+ private URI fixInvalidGithubUrl (final String invalidUrl ) throws IOException {
68
+ // There's a bug in github where it gives you back non-url-encoded characters
69
+ // in the protection_url field. For example if your branch has a single "%" in its name.
70
+ // As of this writing, the protection URL looks something like this
71
+ // https://github-server.tld/api/v3/repos/owner/repo-name/branches/branch-name/protection
72
+ final String [] schemaAndPath = invalidUrl .split ("//" );
73
+ String [] pathParts = schemaAndPath [1 ].split ("/" );
74
+ for (int i = 0 ; i < pathParts .length ; i ++) {
75
+ pathParts [i ] = URLEncoder .encode (pathParts [i ], StandardCharsets .UTF_8 );
76
+ }
77
+ String fixedUrlString = schemaAndPath [0 ] + "//" + String .join ("/" , pathParts );
78
+ return URI .create (fixedUrlString );
79
+ }
80
+
81
+ @ Override
82
+ public ImmutableBranch deserialize (final JsonParser jsonParser , final DeserializationContext deserializationContext )
83
+ throws IOException {
84
+ JsonNode node = jsonParser .getCodec ().readTree (jsonParser );
85
+ URI protectionUrl ;
86
+ var immutableBranchBuilder = ImmutableBranch .builder ();
87
+ if (node .has ("protected" )) {
88
+ immutableBranchBuilder .isProtected (node .get ("protected" ).asBoolean ());
89
+ String protectionUrlString = node .get ("protection_url" ).asText ();
90
+ try {
91
+ protectionUrl = new URI (protectionUrlString );
92
+ } catch (URISyntaxException e ) {
93
+ protectionUrl = fixInvalidGithubUrl (protectionUrlString );
94
+ }
95
+ immutableBranchBuilder .protectionUrl (protectionUrl );
96
+ }
97
+ ImmutableShaLink shaLink = ImmutableShaLink .builder ()
98
+ .sha (node .get ("commit" ).get ("sha" ).asText ())
99
+ .url (URI .create (node .at ("/commit/url" ).asText ()))
100
+ .build ();
101
+ return immutableBranchBuilder
102
+ .name (node .get ("name" ).textValue ())
103
+ .commit (shaLink )
104
+ .build ();
105
+ }
106
+ }
0 commit comments