Skip to content
This repository has been archived by the owner on Jul 3, 2019. It is now read-only.

Commit

Permalink
Merge 8d0493c into c700622
Browse files Browse the repository at this point in the history
  • Loading branch information
zkat committed Mar 16, 2017
2 parents c700622 + 8d0493c commit b61f7d0
Show file tree
Hide file tree
Showing 10 changed files with 445 additions and 19 deletions.
38 changes: 21 additions & 17 deletions lib/finalize-manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,13 @@ function finalizeManifest (pkg, spec, opts) {
if (err) { return cb(err) }
// normalize should not add any fields, and once
// makeManifest completes, it should never be modified.
var result = pkg ? new Manifest(pkg, props) : new Manifest(props)
var result = pkg && pkg.name
? new Manifest(pkg, props)
: new Manifest(props)
if (opts.cache) {
opts.metadata = result
cache.put(
opts.cache,
finalKey(result, spec),
'.',
opts
opts.cache, key || finalKey(result, spec), '.', opts
).then(() => cb(null, result), cb)
} else {
cb(null, result)
Expand Down Expand Up @@ -76,7 +75,7 @@ function Manifest (pkg, fromTarball) {

if (this.bin && Array.isArray(this.bin)) {
// Code yanked from read-package-json.
const m = pkg.directories && pkg.directories.bin || '.'
const m = (pkg.directories && pkg.directories.bin) || '.'
this.bin = this.bin.reduce((acc, mf) => {
if (mf && mf.charAt(0) !== '.') {
const f = path.basename(mf)
Expand Down Expand Up @@ -105,17 +104,17 @@ function Manifest (pkg, fromTarball) {
function tarballedProps (pkg, spec, opts, cb) {
cb = dezalgo(cb)
const extraProps = {}
const needsShrinkwrap = (!pkg ||
const needsShrinkwrap = (!pkg || (
pkg._hasShrinkwrap !== false &&
!pkg._shrinkwrap
)
const needsBin = !!(!pkg ||
))
const needsBin = !!(!pkg || (
!pkg.bin &&
pkg.directories &&
pkg.directories.bin
)
))
const needsShasum = !pkg || !pkg._shasum
const needsManifest = !pkg
const needsManifest = !pkg || !pkg.name
if (!needsShrinkwrap && !needsBin && !needsShasum && !needsManifest) {
opts.log.silly('finalize-manifest', 'Skipping tarball extraction -- nothing needed.')
return cb(null, extraProps)
Expand Down Expand Up @@ -207,11 +206,16 @@ function tarballedProps (pkg, spec, opts, cb) {
}

function finalKey (pkg, spec) {
return (
pkg && (pkg._sha512sum || pkg._shasum) &&
cache.key(
`${spec.type}-manifest`,
`${pkg._sha512sum || pkg._shasum}-${pkg._resolved}`
if (pkg && pkg._uniqueResolved) {
// git packages have a unique, identifiable id, but no tar sha
return cache.key(`${spec.type}-manifest`, pkg._uniqueResolved)
} else {
return (
pkg && (pkg._sha512sum || pkg._shasum) &&
cache.key(
`${spec.type}-manifest`,
`${pkg._sha512sum || pkg._shasum}-${pkg._resolved}`
)
)
)
}
}
63 changes: 63 additions & 0 deletions lib/handlers/git/manifest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
'use strict'

const BB = require('bluebird')

const git = require('../../util/git')
const normalizeGitUrl = require('normalize-git-url')
const optCheck = require('../../util/opt-check')
const pickManifest = require('../../registry/pick-manifest')
const semver = require('semver')

module.exports = manifest
function manifest (spec, opts) {
opts = optCheck(opts)
// TODO - spec.hosted url stuff should be done in hosted handler
const normed = normalizeGitUrl(spec.hosted ? spec.hosted.ssh : spec.spec)
const rawRef = decodeURIComponent(normed.branch)
return resolve(
normed.url, rawRef, spec.name, opts
).then(ref => {
if (ref) {
return {
_repo: normed.url,
_resolved: `${normed.url}#${ref.sha}`,
_spec: spec,
_ref: ref,
_rawRef: rawRef,
_uniqueResolved: `${normed.url}#${ref.sha}`
}
} else {
// We're SOL and need a full clone :(
//
// If we're confident enough that `rawRef` is a commit SHA,
// then we can at least get `finalize-manifest` to cache its result.
return {
_repo: normed.url,
_rawRef: rawRef,
_resolved: rawRef.match(/^[a-f0-9]{40}$/) && `${normed.url}#${rawRef}`,
_uniqueResolved: rawRef.match(/^[a-f0-9]{40}$/) && `${normed.url}#${rawRef}`
}
}
})
}

function resolve (url, rawRef, name, opts) {
const semverMatch = rawRef.match(/^semver:v?(.*)/)
const isSemver = semverMatch && semver.validRange(semverMatch[1])
return git.revs(url, opts).then(remoteRefs => {
return isSemver
? pickManifest({
versions: remoteRefs.versions,
'dist-tags': remoteRefs['dist-tags'],
name: name
}, {
type: 'range',
spec: semverMatch[1]
}, opts)
: remoteRefs
? BB.resolve(
remoteRefs.refs[rawRef] || remoteRefs.refs[remoteRefs.shas[rawRef]]
)
: null
})
}
119 changes: 119 additions & 0 deletions lib/handlers/git/tarball.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
'use strict'

const BB = require('bluebird')

const cache = require('../../cache')
const git = require('../../util/git')
const mkdirp = BB.promisify(require('mkdirp'))
const optCheck = require('../../util/opt-check')
const osenv = require('osenv')
const path = require('path')
const pipe = BB.promisify(require('mississippi').pipe)
const rimraf = BB.promisify(require('rimraf'))
const tar = require('tar-fs')
const through = require('mississippi').through
const to = require('mississippi').to
const uniqueFilename = require('unique-filename')

const gitManifest = require('./manifest')

module.exports = tarball
function tarball (spec, opts) {
opts = optCheck(opts)
let streamErr = null
const stream = through().on('error', e => { streamErr = e })
gitManifest(spec, opts).then(manifest => {
if (streamErr) { throw streamErr }
return pipe(fromManifest(manifest, spec, opts), stream)
})
return stream
}

module.exports.fromManifest = fromManifest
function fromManifest (manifest, spec, opts) {
opts = optCheck(opts)
let streamError
const stream = through().on('error', e => { streamError = e })
const cacheStream = (
opts.cache &&
cache.get.stream(
opts.cache, cache.key('git-clone', manifest._resolved), opts
)
)
cacheStream.pipe(stream)
cacheStream.on('error', err => {
if (err.code !== 'ENOENT') {
return stream.emit('error', err)
} else {
stream.emit('reset')
withTmp(opts, tmp => {
if (streamError) { throw streamError }
return cloneRepo(
manifest._repo, manifest._ref, manifest._rawRef, tmp, opts
).then(HEAD => {
if (streamError) { throw streamError }
return packDir(manifest._resolved, tmp, stream, opts)
})
}).catch(err => stream.emit('error', err))
}
})
return stream
}

function withTmp (opts, cb) {
if (opts.cache) {
// cacache has a special facility for working in a tmp dir
return cache.tmp.withTmp(opts.cache, opts, cb)
} else {
const tmpDir = path.join(osenv.tmpdir(), 'pacote-git-tmp')
const tmpName = uniqueFilename(tmpDir, 'git-clone')
const tmp = mkdirp(tmpName).then(() => tmpName).disposer(rimraf)
return BB.using(tmp, cb)
}
}

function cloneRepo (repo, resolvedRef, rawRef, tmp, opts) {
// TODO - loop through alternatives for hosted specs
if (resolvedRef) {
return git.shallow(repo, resolvedRef.ref, tmp, opts)
} else {
return git.clone(repo, rawRef, tmp, opts)
}
}

function packDir (label, tmp, target, opts) {
opts = optCheck(opts)

// TODO - make a better attempt at a pack
const packer = tar.pack(tmp, {
map: header => {
header.name = 'package/' + header.name
},
ignore: (name) => {
name.match(/\.git/)
}
})

if (!opts.cache) {
return pipe(packer, target)
} else {
const cacher = cache.put.stream(
opts.cache, cache.key('git-clone', label), opts
)
cacher.once('error', err => packer.emit('error', err))
target.once('error', err => packer.emit('error', err))
packer.once('error', err => {
cacher.emit('error', err)
target.emit('error', err)
})
return pipe(packer, to((chunk, enc, cb) => {
cacher.write(chunk, enc, () => {
target.write(chunk, enc, cb)
})
}, done => {
cacher.end(() => {
target.end(done)
})
}))
}
}
3 changes: 3 additions & 0 deletions lib/handlers/hosted/manifest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
'use strict'

module.exports = require('../git/manifest')
3 changes: 3 additions & 0 deletions lib/handlers/hosted/tarball.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
'use strict'

module.exports = require('../git/tarball')
Loading

0 comments on commit b61f7d0

Please sign in to comment.