Skip to content
This repository was archived by the owner on Sep 9, 2020. It is now read-only.

Commit 9e038e6

Browse files
committedSep 11, 2017
Ensure URLs are folded as well
Also add an up-front check for case variant map lookup misses, and update the map accordingly.
1 parent a665a6e commit 9e038e6

File tree

2 files changed

+47
-13
lines changed

2 files changed

+47
-13
lines changed
 

‎internal/gps/manager_test.go

+18-8
Original file line numberDiff line numberDiff line change
@@ -349,8 +349,8 @@ func TestMgrMethodsFailWithBadPath(t *testing.T) {
349349
}
350350

351351
type sourceCreationTestFixture struct {
352-
roots []ProjectIdentifier
353-
urlcount, srccount int
352+
roots []ProjectIdentifier
353+
namecount, srccount int
354354
}
355355

356356
func (f sourceCreationTestFixture) run(t *testing.T) {
@@ -365,8 +365,8 @@ func (f sourceCreationTestFixture) run(t *testing.T) {
365365
}
366366
}
367367

368-
if len(sm.srcCoord.nameToURL) != f.urlcount {
369-
t.Errorf("want %v names in the name->url map, but got %v. contents: \n%v", f.urlcount, len(sm.srcCoord.nameToURL), sm.srcCoord.nameToURL)
368+
if len(sm.srcCoord.nameToURL) != f.namecount {
369+
t.Errorf("want %v names in the name->url map, but got %v. contents: \n%v", f.namecount, len(sm.srcCoord.nameToURL), sm.srcCoord.nameToURL)
370370
}
371371

372372
if len(sm.srcCoord.srcs) != f.srccount {
@@ -390,16 +390,26 @@ func TestSourceCreationCounts(t *testing.T) {
390390
mkPI("gopkg.in/sdboyer/gpkt.v2"),
391391
mkPI("gopkg.in/sdboyer/gpkt.v3"),
392392
},
393-
urlcount: 6,
394-
srccount: 3,
393+
namecount: 6,
394+
srccount: 3,
395395
},
396396
"gopkgin separation from github": {
397397
roots: []ProjectIdentifier{
398398
mkPI("gopkg.in/sdboyer/gpkt.v1"),
399399
mkPI("github.com/sdboyer/gpkt"),
400400
},
401-
urlcount: 4,
402-
srccount: 2,
401+
namecount: 4,
402+
srccount: 2,
403+
},
404+
"case variance across path and URL-based access": {
405+
roots: []ProjectIdentifier{
406+
ProjectIdentifier{ProjectRoot: ProjectRoot("github.com/sdboyer/gpkt"), Source: "https://github.com/Sdboyer/gpkt"},
407+
mkPI("github.com/sdboyer/gpkt"),
408+
ProjectIdentifier{ProjectRoot: ProjectRoot("github.com/sdboyer/gpkt"), Source: "https://github.com/sdboyeR/gpkt"},
409+
mkPI("github.com/sdboyeR/gpkt"),
410+
},
411+
namecount: 5,
412+
srccount: 1,
403413
},
404414
}
405415

‎internal/gps/source.go

+29-5
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ func (sc *sourceCoordinator) getSourceGatewayFor(ctx context.Context, id Project
8383
}
8484
panic(fmt.Sprintf("%q was URL for %q in nameToURL, but no corresponding srcGate in srcs map", url, normalizedName))
8585
}
86-
sc.srcmut.RUnlock()
8786

8887
// Without a direct match, we must fold the input name to a generally
8988
// stable, caseless variant and primarily work from that. This ensures that
@@ -103,6 +102,31 @@ func (sc *sourceCoordinator) getSourceGatewayFor(ctx context.Context, id Project
103102
// systems. So we follow this path, which is both a vastly simpler solution
104103
// and one that seems quite likely to work in practice.
105104
foldedNormalName := toFold(normalizedName)
105+
if foldedNormalName != normalizedName {
106+
// If the folded name differs from the input name, then there may
107+
// already be an entry for it in the nameToURL map, so check again.
108+
if url, has := sc.nameToURL[foldedNormalName]; has {
109+
// There was a match on the canonical folded variant. Upgrade to a
110+
// write lock, so that future calls on this name don't need to
111+
// burn cycles on folding.
112+
sc.srcmut.RUnlock()
113+
sc.srcmut.Lock()
114+
// It may be possible that another goroutine could interleave
115+
// between the unlock and re-lock. Even if they do, though, they'll
116+
// only have recorded the same url value as we have here. In other
117+
// words, these operations commute, so we can safely write here
118+
// without checking again.
119+
sc.nameToURL[normalizedName] = url
120+
121+
srcGate, has := sc.srcs[url]
122+
sc.srcmut.Unlock()
123+
if has {
124+
return srcGate, nil
125+
}
126+
panic(fmt.Sprintf("%q was URL for %q in nameToURL, but no corresponding srcGate in srcs map", url, normalizedName))
127+
}
128+
}
129+
sc.srcmut.RUnlock()
106130

107131
// No gateway exists for this path yet; set up a proto, being careful to fold
108132
// together simultaneous attempts on the same case-folded path.
@@ -140,7 +164,7 @@ func (sc *sourceCoordinator) getSourceGatewayFor(ctx context.Context, id Project
140164
sc.psrcmut.Unlock()
141165
}
142166

143-
pd, err := sc.deducer.deduceRootPath(ctx, normalizedName)
167+
pd, err := sc.deducer.deduceRootPath(ctx, foldedNormalName)
144168
if err != nil {
145169
// As in the deducer, don't cache errors so that externally-driven retry
146170
// strategies can be constructed.
@@ -189,15 +213,15 @@ func (sc *sourceCoordinator) getSourceGatewayFor(ctx context.Context, id Project
189213
defer sc.srcmut.Unlock()
190214
// Record the name -> URL mapping, making sure that we also get the
191215
// self-mapping.
192-
sc.nameToURL[normalizedName] = url
193-
if url != normalizedName {
216+
sc.nameToURL[foldedNormalName] = url
217+
if url != foldedNormalName {
194218
sc.nameToURL[url] = url
195219
}
196220

197221
// Make sure we have both the folded and unfolded names recorded in the map,
198222
// should they differ.
199223
if normalizedName != foldedNormalName {
200-
sc.nameToURL[foldedNormalName] = url
224+
sc.nameToURL[normalizedName] = url
201225
}
202226

203227
if sa, has := sc.srcs[url]; has {

0 commit comments

Comments
 (0)
This repository has been archived.