Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.1.4

- Fixed bug where attempting to checkout a new tag present only on the remote incorrectly reported the clone was already on that version.

## 1.1.3

- Added option to enable checking out rather than recloning when changing versions via `FALLBACK_DEPENDENCIES_ENABLE_CHECKOUT` environment variable or `enableCheckout` in `fallbackDependencies` package.json config.
Expand Down
10 changes: 5 additions & 5 deletions fallback-dependencies.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ function executeFallbackList (listTypes) {
break
}
}
const fetch = spawnSync('git', ['fetch', '--tags'], { // make sure current clone has all tags
shell: false,
cwd: path.resolve(fallbackDependenciesDir + '/' + dependency, '')
})
if (fetch.status !== 0) throw fetch.stderr.toString()
const output = spawnSync('git', ['tag'], { // get list of tags
shell: false,
cwd: path.resolve(fallbackDependenciesDir + '/' + dependency, '')
Expand All @@ -153,11 +158,6 @@ function executeFallbackList (listTypes) {
if (!rerunNpmCi) break // stop checking fallbacks
} else { // version supplied is a valid tag, but differs from current tag
if (enableCheckout) {
const fetch = spawnSync('git', ['fetch', '--tags'], {
shell: false,
cwd: path.resolve(fallbackDependenciesDir + '/' + dependency, '')
})
if (fetch.status !== 0) throw fetch.stderr.toString()
const checkout = spawnSync('git', ['checkout', version], {
shell: false,
cwd: path.resolve(fallbackDependenciesDir + '/' + dependency, '')
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"url": "https://github.com/rooseveltframework/fallback-dependencies/graphs/contributors"
}
],
"version": "1.1.3",
"version": "1.1.4",
"files": [
"fallback-dependencies.js",
"*.md"
Expand Down
16 changes: 15 additions & 1 deletion test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const failedToClone = path.join(__dirname, './util/failedToClone')
const failedToCloneVersion = path.join(__dirname, './util/failedToCloneVersion')
const gitCheckoutTagError = path.join(__dirname, './util/gitCheckoutTagError.js')
const gitCheckoutCommitError = path.join(__dirname, './util/gitCheckoutCommitError.js')
const gitCheckoutTag = path.join(__dirname, './util/gitCheckoutTag.js')
const gitCloneCheckoutError = path.join(__dirname, './util/gitCloneCheckoutError.js')
const gitError = path.join(__dirname, './util/gitError.js')
const gitFetchHeadError = path.join(__dirname, './util/gitFetchHeadError.js')
Expand Down Expand Up @@ -153,6 +154,19 @@ describe('universal fallback-dependencies tests', () => {
delete process.env.FALLBACK_DEPENDENCIES_ENABLE_CHECKOUT
})

it('should checkout a specific git tag even when current clone is behind remote repo', () => {
process.env.FALLBACK_DEPENDENCIES_ENABLE_CHECKOUT = true
const listTypes = ['fallbackDependencies', 'fallbackDevDependencies']
while (listTypes.length) {
fs.rmSync(path.join(__dirname, './clones'), { recursive: true, force: true })
fs.rmSync(path.join(__dirname, './repos'), { recursive: true, force: true })
require(gitCheckoutTag)(listTypes.pop())
assert(fs.existsSync(path.join(__dirname, './clones/repo1/lib')), './clones/repo1/lib does not exist')
assert(fs.existsSync(path.join(__dirname, './clones/repo1/lib/fallback-deps-test-repo-2')), './clones/repo1/lib/fallback-deps-test-repo-2 does not exist')
}
delete process.env.FALLBACK_DEPENDENCIES_ENABLE_CHECKOUT
})

it('should checkout a non-tagged commit', () => {
const listTypes = ['fallbackDependencies', 'fallbackDevDependencies']
while (listTypes.length) {
Expand Down Expand Up @@ -343,7 +357,7 @@ describe('universal fallback-dependencies tests', () => {
fs.rmSync(path.join(__dirname, './clones'), { recursive: true, force: true })
fs.rmSync(path.join(__dirname, './repos'), { recursive: true, force: true })
const output = require(gitTagError)('fallbackDependencies')
assert(output.includes('fatal: unterminated line in'), 'git tag command didn\'t throw an error')
assert(output.includes('fatal: simulated git tag error'), 'git tag command didn\'t throw an error')
})

it('should throw an error if the "git fetch --tags" command fails', () => {
Expand Down
179 changes: 179 additions & 0 deletions test/util/gitCheckoutTag.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
module.exports = (listType) => {
const fs = require('fs')
const path = require('path')
const { spawnSync } = require('child_process')
const testSrc = path.resolve(__dirname, '../../test')
const repoList = ['repo1', 'repo2', 'repo3']

try {
fs.rmSync(path.join(__dirname, './clones'), { recursive: true, force: true })
fs.rmSync(path.join(__dirname, './repos'), { recursive: true, force: true })
if (!fs.existsSync(`${testSrc}/repos`)) fs.mkdirSync(`${testSrc}/repos`)
if (!fs.existsSync(`${testSrc}/clones`)) fs.mkdirSync(`${testSrc}/clones`)

const repo1Package = {
dependencies: {
'fallback-dependencies': '../../../'
},
scripts: {
postinstall: 'node node_modules/fallback-dependencies/fallback-dependencies.js'
}
}
repo1Package[listType] = {
dir: 'lib',
reposFile: 'reposFile.json'
}
const repo1PackageLock = {
name: 'repo1',
lockfileVersion: 3,
requires: true,
packages: {
'': {
hasInstallScript: true,
dependencies: {
'fallback-dependencies': '../../..'
}
},
'../../..': {
version: '0.1.0',
license: 'CC-BY-1.0',
dependencies: {}
},
'node_modules/fallback-dependencies': {
resolved: '../../..',
link: true
}
}
}
let repo1FileData = {
'fallback-deps-test-repo-2': [
'../../../repos/repo2'
]
}
const repo2Package = {
dependencies: {
'fallback-dependencies': '../../../../../'
},
scripts: {
postinstall: 'node node_modules/fallback-dependencies/fallback-dependencies.js'
}
}
repo2Package[listType] = {
dir: 'lib',
repos: {
'fallback-deps-test-repo-3:': '../../../../../repos/repo3'
}
}
const repo2PackageLock = {
name: 'repo2',
lockfileVersion: 3,
requires: true,
packages: {
'': {
hasInstallScript: true,
dependencies: {
'fallback-dependencies': '../../../../..'
}
},
'../../../../..': {
version: '0.1.0',
license: 'CC-BY-1.0',
dependencies: {}
},
'node_modules/fallback-dependencies': {
resolved: '../../../../..',
link: true
}
}
}
const repo3Package = {}
const repo3PackageLock = {
name: 'repo3',
lockfileVersion: 3,
requires: true,
packages: {}
}

// initialize repos
const packageList = [[repo1Package, repo1PackageLock], [repo2Package, repo2PackageLock], [repo3Package, repo3PackageLock]]
for (const id in repoList) {
if (!fs.existsSync(`${testSrc}/repos/${repoList[id]}/`)) fs.mkdirSync(`${testSrc}/repos/${repoList[id]}/`)
spawnSync('git', ['--bare', 'init'], {
shell: false,
stdio: 'pipe', // hide output from git
cwd: path.normalize(`${testSrc}/repos/${repoList[id]}`, '') // where we're cloning the repo to
})
spawnSync('git', ['clone', `${testSrc}/repos/${repoList[id]}`], {
shell: false,
stdio: 'pipe', // hide output from git
cwd: path.normalize(`${testSrc}/clones`, '') // where we're cloning the repo to
})
if (repoList[id] === 'repo1') fs.writeFileSync(`${testSrc}/clones/repo1/reposFile.json`, JSON.stringify(repo1FileData))
fs.writeFileSync(`${testSrc}/clones/${repoList[id]}/package.json`, JSON.stringify(packageList[id][0]))
fs.writeFileSync(`${testSrc}/clones/${repoList[id]}/package-lock.json`, JSON.stringify(packageList[id][1]))
spawnSync('git', ['add', '.'], {
shell: false,
stdio: 'pipe', // hide output from git
cwd: path.normalize(`${testSrc}/clones/${repoList[id]}`, '') // where we're cloning the repo to
})
spawnSync('git', ['commit', '-m', '"commit"'], {
shell: false,
stdio: 'pipe', // hide output from git
cwd: path.normalize(`${testSrc}/clones/${repoList[id]}`, '') // where we're cloning the repo to
})
spawnSync('git', ['push'], {
shell: false,
stdio: 'pipe', // hide output from git
cwd: path.normalize(`${testSrc}/clones/${repoList[id]}`, '') // where we're cloning the repo to
})
}

// add 1.0.0 tag and attempt to clone repo while specifying it
spawnSync('git', ['tag', '1.0.0'], {
shell: false,
stdio: 'pipe', // hide output from git
cwd: path.normalize(`${testSrc}/clones/repo2`, '') // where we're cloning the repo to
})
spawnSync('git', ['push', '--tags'], {
shell: false,
stdio: 'pipe', // hide output from git
cwd: path.normalize(`${testSrc}/clones/repo2`, '') // where we're cloning the repo to
})
repo1FileData = {
'fallback-deps-test-repo-2': [
'../../../repos/repo2 -b 1.0.0'
]
}
fs.writeFileSync(`${testSrc}/clones/repo1/reposFile.json`, JSON.stringify(repo1FileData))
spawnSync('npm', ['ci'], {
shell: false,
stdio: 'pipe', // hide output from git
cwd: path.normalize(`${testSrc}/clones/repo1`, '') // where we're cloning the repo to
})

// add 1.0.1 tag and attempt to clone repo while specifying it
spawnSync('git', ['tag', '1.0.1'], {
shell: false,
stdio: 'pipe', // hide output from git
cwd: path.normalize(`${testSrc}/repos/repo2`, '') // where we're cloning the repo to
})
spawnSync('git', ['push', '--tags'], {
shell: false,
stdio: 'pipe', // hide output from git
cwd: path.normalize(`${testSrc}/repos/repo2`, '') // where we're cloning the repo to
})

// attempt to clone repo
repo1FileData = {
'fallback-deps-test-repo-2': [
'../../../repos/repo2 -b 1.0.1'
]
}
fs.writeFileSync(`${testSrc}/clones/repo1/reposFile.json`, JSON.stringify(repo1FileData))
spawnSync('npm', ['ci'], {
shell: false,
stdio: 'pipe', // hide output from git
cwd: path.normalize(`${testSrc}/clones/repo1`, '') // where we're cloning the repo to
})
} catch {}
}
15 changes: 6 additions & 9 deletions test/util/gitFetchRemoteError.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module.exports = (listType) => {
const path = require('path')
const { spawnSync } = require('child_process')
const testSrc = path.resolve(__dirname, '../../test')
const interceptGitFetchRemoteSpawnSyncPath = path.resolve(__dirname, 'interceptGitFetchRemoteSpawnSync.js')
const repoList = ['repo1', 'repo2']

try {
Expand Down Expand Up @@ -139,14 +140,6 @@ module.exports = (listType) => {
cwd: path.normalize(`${testSrc}/clones/repo1`, '') // where we're cloning the repo to
})

// edit git config to trigger error
const config = fs.readFileSync(path.normalize(`${testSrc}/clones/repo1/lib/fallback-deps-test-repo-2/.git/config`)).toString()
const updatedConfig = config.split('\n').map(line => {
if (line.includes('fetch =')) return '\tfetch = not-valid'
return line
}).join('\n')
fs.writeFileSync(path.normalize(`${testSrc}/clones/repo1/lib/fallback-deps-test-repo-2/.git/config`), updatedConfig)

// get commit id and attempt to clone repo while specifying it
const commit = spawnSync('git', ['log', '--oneline'], {
shell: false,
Expand All @@ -162,7 +155,11 @@ module.exports = (listType) => {
const output = spawnSync('npm', ['ci'], {
shell: false,
stdio: 'pipe', // hide output from git
cwd: path.normalize(`${testSrc}/clones/repo1`, '') // where we're cloning the repo to
cwd: path.normalize(`${testSrc}/clones/repo1`, ''), // where we're cloning the repo to
env: {
...process.env,
NODE_OPTIONS: `-r ${interceptGitFetchRemoteSpawnSyncPath} ${process.env.NODE_OPTIONS || ''}`
}
})

return output.stderr.toString()
Expand Down
10 changes: 6 additions & 4 deletions test/util/gitTagError.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module.exports = (listType) => {
const path = require('path')
const { spawnSync } = require('child_process')
const testSrc = path.resolve(__dirname, '../../test')
const interceptGitTagSpawnSyncPath = path.resolve(__dirname, 'interceptGitTagSpawnSync.js')
const repoList = ['repo1', 'repo2']

try {
Expand Down Expand Up @@ -139,13 +140,14 @@ module.exports = (listType) => {
cwd: path.normalize(`${testSrc}/clones/repo1`, '') // where we're cloning the repo to
})

// edit git packed-refs to trigger error
fs.writeFileSync(path.normalize(`${testSrc}/clones/repo1/lib/fallback-deps-test-repo-2/.git/packed-refs`), 'invalid content')

const output = spawnSync('npm', ['ci'], {
shell: false,
stdio: 'pipe', // hide output from git
cwd: path.normalize(`${testSrc}/clones/repo1`, '') // where we're cloning the repo to
cwd: path.normalize(`${testSrc}/clones/repo1`, ''), // where we're cloning the repo to
env: {
...process.env,
NODE_OPTIONS: `-r ${interceptGitTagSpawnSyncPath} ${process.env.NODE_OPTIONS || ''}`
}
})

return output.stderr.toString()
Expand Down
24 changes: 24 additions & 0 deletions test/util/interceptGitFetchRemoteSpawnSync.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const fs = require('fs')
const path = require('path')
const testSrc = path.resolve(__dirname, '../../test')

// replace original spawnSync
const childProcess = require('child_process')
const originalSpawnSync = childProcess.spawnSync
childProcess.spawnSync = function (command, args, options) {
const argv = Array.isArray(args) ? args : []
const isGit = command === 'git'
const isFetchRemote = argv.length === 2 && argv[0] === 'fetch' && argv[1] !== '--tags'

if (isGit && isFetchRemote) {
// edit git config to trigger error
const config = fs.readFileSync(path.normalize(`${testSrc}/clones/repo1/lib/fallback-deps-test-repo-2/.git/config`)).toString()
const updatedConfig = config.split('\n').map(line => {
if (line.includes('fetch =')) return '\tfetch = not-valid'
return line
}).join('\n')
fs.writeFileSync(path.normalize(`${testSrc}/clones/repo1/lib/fallback-deps-test-repo-2/.git/config`), updatedConfig)
}

return originalSpawnSync.apply(this, arguments)
}
23 changes: 23 additions & 0 deletions test/util/interceptGitTagSpawnSync.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// replace original spawnSync
const childProcess = require('child_process')
const originalSpawnSync = childProcess.spawnSync
childProcess.spawnSync = function (command, args, options) {
const argv = Array.isArray(args) ? args : []
const isGit = command === 'git'
const isTag = argv.length === 1 && argv[0] === 'tag'

if (isGit && isTag) {
const msg = 'fatal: simulated git tag error\n'
return {
pid: -1,
output: [null, Buffer.from(''), Buffer.from(msg)],
stdout: Buffer.from(''),
stderr: Buffer.from(msg),
status: 128,
signal: null,
error: null
}
}

return originalSpawnSync.apply(this, arguments)
}
Loading