11import type { Octokit } from "./octokit" ;
2- import { isEqual , none , Option , some } from "./option" ;
2+ import { isEqual , isSome , none , Option , some } from "./option" ;
33
44import {
55 isExactSemanticVersion ,
@@ -14,7 +14,8 @@ type Commit = {
1414 sha : Sha ;
1515} ;
1616
17- type Tag = {
17+ // This type is only exported for testing.
18+ export type Tag = {
1819 name : SemanticVersion ;
1920 commit : Commit ;
2021} ;
@@ -30,6 +31,56 @@ function containsExactTag(
3031 return tags . find ( isExactSemanticVersion ) ;
3132}
3233
34+ // This function is only exported for testing.
35+ export function exactSemanticVersionTagReducer ( givenTag : SemanticVersion ) {
36+ const versionsBySha : Record < Sha , SemanticVersion [ ] > = { } ;
37+ let givenTagSha : Option < Sha > = none ( ) ;
38+
39+ // Conditions for an exact match are -- we know both the:
40+ //
41+ // - sha that the given tag points to
42+ // - exact version tag matching that sha
43+ //
44+ // These can be found in either order.
45+ return function reducer ( tag : Tag ) : Option < ExactSemanticVersion > {
46+ const sha = tag . commit . sha ;
47+ const version = tag . name ;
48+
49+ // If we found the sha the given tag points to
50+ if ( version === givenTag ) {
51+ givenTagSha = some ( sha ) ;
52+ // check if we already knew the exact version tag matching that sha
53+ const maybeExactTag = containsExactTag ( versionsBySha [ sha ] ) ;
54+ if ( maybeExactTag !== undefined ) {
55+ return some ( maybeExactTag ) ;
56+ }
57+ }
58+
59+ // If we're not looking at the given tag, and we're not looking
60+ // at an exact version, this data is of no use to us.
61+ if ( ! isExactSemanticVersion ( version ) ) {
62+ return none ( ) ;
63+ }
64+
65+ // It is possible that we know the sha for the given tag,
66+ // we're just looking for exact version tag matching that sha.
67+ if ( isEqual ( givenTagSha , sha ) ) {
68+ return some ( version ) ;
69+ }
70+
71+ // Otherwise, record this map of sha -> exact version tag
72+ // so we can find it when we know the sha of the given tag.
73+ const associatedVersions = versionsBySha [ sha ] ;
74+ if ( associatedVersions === undefined ) {
75+ versionsBySha [ sha ] = [ version ] ;
76+ } else {
77+ associatedVersions . push ( version ) ;
78+ }
79+
80+ return none ( ) ;
81+ } ;
82+ }
83+
3384// Find the exact semantic version tag that this tag maps to.
3485//
3586// We need an exact tag because that's the only accepted input
@@ -43,15 +94,7 @@ export async function findExactSemanticVersionTag(
4394 return givenTag ;
4495 }
4596
46- const versionsBySha : Record < Sha , SemanticVersion [ ] > = { } ;
47- let givenTagSha : Option < Sha > = none ( ) ;
48-
49- // Conditions to stop looping are -- we know both the:
50- //
51- // - sha that the given tag points to
52- // - exact version tag matching that sha
53- //
54- // These can be found in either order.
97+ const reducer = exactSemanticVersionTagReducer ( givenTag ) ;
5598
5699 for await ( const response of octokit . paginate . iterator (
57100 octokit . rest . repos . listTags ,
@@ -63,38 +106,9 @@ export async function findExactSemanticVersionTag(
63106 ) ) {
64107 // NOTE: we are not parsing here, so this is an unlawful type cast
65108 for ( const tag of response . data as unknown as TagsResponse ) {
66- const sha = tag . commit . sha ;
67- const version = tag . name ;
68-
69- // If we found the sha the given tag points to
70- if ( version === givenTag ) {
71- givenTagSha = some ( sha ) ;
72- // check if we already knew the exact version tag matching that sha
73- const maybeExactTag = containsExactTag ( versionsBySha [ sha ] ) ;
74- if ( maybeExactTag !== undefined ) {
75- return maybeExactTag ;
76- }
77- }
78-
79- // If we're not looking at the given tag, and we're not looking
80- // at an exact version, this data is of no use to us.
81- if ( ! isExactSemanticVersion ( version ) ) {
82- continue ;
83- }
84-
85- // It is possible that we know the sha for the given tag,
86- // we're just looking for exact version tag matching that sha.
87- if ( isEqual ( givenTagSha , sha ) ) {
88- return version ;
89- }
90-
91- // Otherwise, record this map of sha -> exact version tag
92- // so we can find it when we know the sha of the given tag.
93- const associatedVersions = versionsBySha [ sha ] ;
94- if ( associatedVersions === undefined ) {
95- versionsBySha [ sha ] = [ version ] ;
96- } else {
97- associatedVersions . push ( version ) ;
109+ const maybeExactTag = reducer ( tag ) ;
110+ if ( isSome ( maybeExactTag ) ) {
111+ return maybeExactTag . value ;
98112 }
99113 }
100114 }
0 commit comments