source: trip-planner-front/node_modules/@npmcli/git/lib/lines-to-revs.js@ b738035

Last change on this file since b738035 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 3.9 KB
Line 
1// turn an array of lines from `git ls-remote` into a thing
2// vaguely resembling a packument, where docs are a resolved ref
3
4const semver = require('semver')
5
6module.exports = lines => finish(lines.reduce(linesToRevsReducer, {
7 versions: {},
8 'dist-tags': {},
9 refs: {},
10 shas: {}
11}))
12
13const finish = revs => distTags(shaList(peelTags(revs)))
14
15// We can check out shallow clones on specific SHAs if we have a ref
16const shaList = revs => {
17 Object.keys(revs.refs).forEach(ref => {
18 const doc = revs.refs[ref]
19 if (!revs.shas[doc.sha]) {
20 revs.shas[doc.sha] = [ref]
21 } else {
22 revs.shas[doc.sha].push(ref)
23 }
24 })
25 return revs
26}
27
28// Replace any tags with their ^{} counterparts, if those exist
29const peelTags = revs => {
30 Object.keys(revs.refs).filter(ref => ref.endsWith('^{}')).forEach(ref => {
31 const peeled = revs.refs[ref]
32 const unpeeled = revs.refs[ref.replace(/\^\{\}$/, '')]
33 if (unpeeled) {
34 unpeeled.sha = peeled.sha
35 delete revs.refs[ref]
36 }
37 })
38 return revs
39}
40
41const distTags = revs => {
42 // not entirely sure what situations would result in an
43 // ichabod repo, but best to be careful in Sleepy Hollow anyway
44 const HEAD = revs.refs.HEAD || /* istanbul ignore next */ {}
45 const versions = Object.keys(revs.versions)
46 versions.forEach(v => {
47 // simulate a dist-tags with latest pointing at the
48 // 'latest' branch if one exists and is a version,
49 // or HEAD if not.
50 const ver = revs.versions[v]
51 if (revs.refs.latest && ver.sha === revs.refs.latest.sha) {
52 revs['dist-tags'].latest = v
53 } else if (ver.sha === HEAD.sha) {
54 revs['dist-tags'].HEAD = v
55 if (!revs.refs.latest) { revs['dist-tags'].latest = v }
56 }
57 })
58 return revs
59}
60
61const refType = ref => {
62 if (ref.startsWith('refs/tags/')) {
63 return 'tag'
64 }
65 if (ref.startsWith('refs/heads/')) {
66 return 'branch'
67 }
68 if (ref.startsWith('refs/pull/')) {
69 return 'pull'
70 }
71 if (ref === 'HEAD') {
72 return 'head'
73 }
74 // Could be anything, ignore for now
75 /* istanbul ignore next */
76 return 'other'
77}
78
79// return the doc, or null if we should ignore it.
80const lineToRevDoc = line => {
81 const split = line.trim().split(/\s+/, 2)
82 if (split.length < 2) { return null }
83
84 const sha = split[0].trim()
85 const rawRef = split[1].trim()
86 const type = refType(rawRef)
87
88 if (type === 'tag') {
89 // refs/tags/foo^{} is the 'peeled tag', ie the commit
90 // that is tagged by refs/tags/foo they resolve to the same
91 // content, just different objects in git's data structure.
92 // But, we care about the thing the tag POINTS to, not the tag
93 // object itself, so we only look at the peeled tag refs, and
94 // ignore the pointer.
95 // For now, though, we have to save both, because some tags
96 // don't have peels, if they were not annotated.
97 const ref = rawRef.substr('refs/tags/'.length)
98 return { sha, ref, rawRef, type }
99 }
100
101 if (type === 'branch') {
102 const ref = rawRef.substr('refs/heads/'.length)
103 return { sha, ref, rawRef, type }
104 }
105
106 if (type === 'pull') {
107 // NB: merged pull requests installable with #pull/123/merge
108 // for the merged pr, or #pull/123 for the PR head
109 const ref = rawRef.substr('refs/'.length).replace(/\/head$/, '')
110 return { sha, ref, rawRef, type }
111 }
112
113 if (type === 'head') {
114 const ref = 'HEAD'
115 return { sha, ref, rawRef, type }
116 }
117
118 // at this point, all we can do is leave the ref un-munged
119 return { sha, ref: rawRef, rawRef, type }
120}
121
122const linesToRevsReducer = (revs, line) => {
123 const doc = lineToRevDoc(line)
124
125 if (!doc) { return revs }
126
127 revs.refs[doc.ref] = doc
128 revs.refs[doc.rawRef] = doc
129
130 if (doc.type === 'tag') {
131 // try to pull a semver value out of tags like `release-v1.2.3`
132 // which is a pretty common pattern.
133 const match = !doc.ref.endsWith('^{}') &&
134 doc.ref.match(/v?(\d+\.\d+\.\d+(?:[-+].+)?)$/)
135 if (match && semver.valid(match[1], true)) {
136 revs.versions[semver.clean(match[1], true)] = doc
137 }
138 }
139
140 return revs
141}
Note: See TracBrowser for help on using the repository browser.