summaryrefslogtreecommitdiff
path: root/deps/npm/test/tap/install-shrinkwrapped-git.js
blob: f74e185bfbad0e9814fa0eebffd09eaec995dcc9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
'use strict'

var fs = require('fs')
var path = require('path')
var resolve = path.resolve
var osenv = require('osenv')
var mkdirp = require('mkdirp')
var rimraf = require('rimraf')
var test = require('tap').test
var npm = require('../../lib/npm')
var common = require('../common-tap')
var chain = require('slide').chain

var mockPath = common.pkg
var parentPath = resolve(mockPath, 'parent')
var parentNodeModulesPath = path.join(parentPath, 'node_modules')
var outdatedNodeModulesPath = resolve(mockPath, 'node-modules-backup')
var childPath = resolve(mockPath, 'child.git')

var gitDaemon
var gitDaemonPID
var git

var parentPackageJSON = JSON.stringify({
  name: 'parent',
  version: '0.1.0'
})

var childPackageJSON = JSON.stringify({
  name: 'child',
  version: '0.1.0'
})

test('setup', function (t) {
  cleanup()
  setup(function (err, result) {
    t.ifError(err, 'git started up successfully')

    if (!err) {
      gitDaemon = result[result.length - 2]
      gitDaemonPID = result[result.length - 1]
    }

    t.end()
  })
})

test('shrinkwrapped git dependency got updated', function (t) {
  t.comment('test for https://github.com/npm/npm/issues/12718')

  // Prepare the child package git repo with two commits
  prepareChildAndGetRefs(function (err, refs) {
    if (err) { throw err }
    chain([
      // Install & shrinkwrap child package's first commit
      [npm.commands.install, ['git://localhost:' + common.gitPort + '/child.git#' + refs[0]]],
      // Backup node_modules with the first commit
      [fs.rename, parentNodeModulesPath, outdatedNodeModulesPath],
      // Install & shrinkwrap child package's latest commit
      [npm.commands.install, ['git://localhost:' + common.gitPort + '/child.git#' + refs[1].substr(0, 8)]],
      // Restore node_modules with the first commit
      [rimraf, parentNodeModulesPath],
      [fs.rename, outdatedNodeModulesPath, parentNodeModulesPath],
      // Update node_modules
      [npm.commands.install, []]
    ], function () {
      const pkglock = require(path.join(parentPath, 'package-lock.json'))
      t.similar(pkglock, {
        dependencies: {
          child: {
            version: `git://localhost:${common.gitPort}/child.git#${refs[1]}`,
            from: `git://localhost:${common.gitPort}/child.git#${refs[1].substr(0, 8)}`
          }
        }
      }, 'version and from fields are correct in git-based pkglock dep')
      var childPackageJSON = require(path.join(parentNodeModulesPath, 'child', 'package.json'))
      t.equal(
        childPackageJSON._resolved,
        'git://localhost:' + common.gitPort + '/child.git#' + refs[1],
        "Child package wasn't updated"
      )
      t.end()
    })
  })
})

test('clean', function (t) {
  gitDaemon.on('close', function () {
    cleanup()
    t.end()
  })
  process.kill(gitDaemonPID)
})

function setup (cb) {
  // Setup parent package
  mkdirp.sync(parentPath)
  fs.writeFileSync(resolve(parentPath, 'package.json'), parentPackageJSON)
  process.chdir(parentPath)

  // Setup child
  mkdirp.sync(childPath)
  fs.writeFileSync(resolve(childPath, 'package.json'), childPackageJSON)

  // Setup npm and then git
  npm.load({
    registry: common.registry,
    loglevel: 'silent',
    save: true // Always install packages with --save
  }, function () {
    // It's important to initialize git after npm because it uses config
    initializeGit(cb)
  })
}

function cleanup () {
  process.chdir(osenv.tmpdir())
  rimraf.sync(mockPath)
}

function prepareChildAndGetRefs (cb) {
  var opts = { cwd: childPath, env: { PATH: process.env.PATH } }
  chain([
    [fs.writeFile, path.join(childPath, 'README.md'), ''],
    git.chainableExec(['add', 'README.md'], opts),
    git.chainableExec(['commit', '-m', 'Add README'], opts),
    git.chainableExec(['log', '--pretty=format:"%H"', '-2'], opts)
  ], function (err) {
    if (err) { return cb(err) }
    var gitLogStdout = arguments[arguments.length - 1]
    var refs = gitLogStdout[gitLogStdout.length - 1].split('\n').map(function (ref) {
      return ref.match(/^"(.+)"$/)[1]
    }).reverse() // Reverse refs order: last, first -> first, last
    cb(null, refs)
  })
}

function initializeGit (cb) {
  git = require('../../lib/utils/git')
  common.makeGitRepo({
    path: childPath,
    commands: [startGitDaemon]
  }, cb)
}

function startGitDaemon (cb) {
  var daemon = git.spawn(
    [
      'daemon',
      '--verbose',
      '--listen=localhost',
      '--export-all',
      '--base-path=' + mockPath, // Path to the dir that contains child.git
      '--reuseaddr',
      '--port=' + common.gitPort
    ],
    {
      cwd: parentPath,
      env: process.env,
      stdio: ['pipe', 'pipe', 'pipe']
    }
  )
  daemon.stderr.on('data', function findChild (c) {
    var cpid = c.toString().match(/^\[(\d+)\]/)
    if (cpid[1]) {
      this.removeListener('data', findChild)
      cb(null, [daemon, cpid[1]])
    }
  })
}