Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
untar.js97 linesDownload Raw Back to lib
1const tar = require('tar')
2const { minimatch } = require('minimatch')
3
4const normalizeMatch = str => str
5  .replace(/\\+/g, '/')
6  .replace(/^\.\/|^\./, '')
7
8// files and refs are mutating params
9// filterFiles, item, prefix and opts are read-only options
10const untar = ({ files, refs }, { filterFiles, item, prefix }) => {
11  tar.list({
12    filter: (path, entry) => {
13      const fileMatch = () =>
14        (!filterFiles.length ||
15          filterFiles.some(f => {
16            const pattern = normalizeMatch(f)
17            return minimatch(
18              normalizeMatch(path),
19              `{package/,}${pattern}`,
20              { matchBase: pattern.startsWith('*') }
21            )
22          }))
23
24      // expands usage of simple path filters, e.g: lib or src/
25      const folderMatch = () =>
26        filterFiles.some(f =>
27          normalizeMatch(path).startsWith(normalizeMatch(f)) ||
28          normalizeMatch(path).startsWith(`package/${normalizeMatch(f)}`))
29
30      if (
31        entry.type === 'File' &&
32        (fileMatch() || folderMatch())
33      ) {
34        const key = path.replace(/^[^/]+\/?/, '')
35        files.add(key)
36
37        // should skip reading file when using --name-only option
38        let content
39        try {
40          content = entry.concat()
41        } catch (e) {
42          /* istanbul ignore next */
43          throw Object.assign(
44            new Error('failed to read files'),
45            { code: 'EDIFFUNTAR' }
46          )
47        }
48
49        refs.set(`${prefix}${key}`, {
50          content,
51          mode: `100${entry.mode.toString(8)}`,
52        })
53        return true
54      }
55    },
56  })
57    .on('error', /* istanbul ignore next */ e => {
58      throw e
59    })
60    .end(item)
61}
62
63const readTarballs = async (tarballs, opts = {}) => {
64  const files = new Set()
65  const refs = new Map()
66  const arr = [].concat(tarballs)
67
68  const filterFiles = opts.diffFiles || []
69
70  for (const i of arr) {
71    untar({
72      files,
73      refs,
74    }, {
75      item: i.item,
76      prefix: i.prefix,
77      filterFiles,
78    })
79  }
80
81  // await to read all content from included files
82  // TODO this feels like it could be one in one pass instead of three (values, map, forEach)
83  const allRefs = [...refs.values()]
84  const contents = await Promise.all(allRefs.map(async ref => ref.content))
85
86  contents.forEach((content, index) => {
87    allRefs[index].content = content.toString('utf8')
88  })
89
90  return {
91    files,
92    refs,
93  }
94}
95
96module.exports = readTarballs
97 
codekingpro/portable-devtools · Team Ai