semver
  1  #!/usr/bin/env node
  2  // Standalone semver comparison program.
  3  // Exits successfully and prints matching version(s) if
  4  // any supplied version is valid and passes all tests.
  5  
  6  var argv = process.argv.slice(2)
  7  
  8  var versions = []
  9  
 10  var range = []
 11  
 12  var inc = null
 13  
 14  var version = require('../package.json').version
 15  
 16  var loose = false
 17  
 18  var includePrerelease = false
 19  
 20  var coerce = false
 21  
 22  var identifier
 23  
 24  var semver = require('../semver')
 25  
 26  var reverse = false
 27  
 28  var options = {}
 29  
 30  main()
 31  
 32  function main () {
 33    if (!argv.length) return help()
 34    while (argv.length) {
 35      var a = argv.shift()
 36      var indexOfEqualSign = a.indexOf('=')
 37      if (indexOfEqualSign !== -1) {
 38        a = a.slice(0, indexOfEqualSign)
 39        argv.unshift(a.slice(indexOfEqualSign + 1))
 40      }
 41      switch (a) {
 42        case '-rv': case '-rev': case '--rev': case '--reverse':
 43          reverse = true
 44          break
 45        case '-l': case '--loose':
 46          loose = true
 47          break
 48        case '-p': case '--include-prerelease':
 49          includePrerelease = true
 50          break
 51        case '-v': case '--version':
 52          versions.push(argv.shift())
 53          break
 54        case '-i': case '--inc': case '--increment':
 55          switch (argv[0]) {
 56            case 'major': case 'minor': case 'patch': case 'prerelease':
 57            case 'premajor': case 'preminor': case 'prepatch':
 58              inc = argv.shift()
 59              break
 60            default:
 61              inc = 'patch'
 62              break
 63          }
 64          break
 65        case '--preid':
 66          identifier = argv.shift()
 67          break
 68        case '-r': case '--range':
 69          range.push(argv.shift())
 70          break
 71        case '-c': case '--coerce':
 72          coerce = true
 73          break
 74        case '-h': case '--help': case '-?':
 75          return help()
 76        default:
 77          versions.push(a)
 78          break
 79      }
 80    }
 81  
 82    var options = { loose: loose, includePrerelease: includePrerelease }
 83  
 84    versions = versions.map(function (v) {
 85      return coerce ? (semver.coerce(v) || { version: v }).version : v
 86    }).filter(function (v) {
 87      return semver.valid(v)
 88    })
 89    if (!versions.length) return fail()
 90    if (inc && (versions.length !== 1 || range.length)) { return failInc() }
 91  
 92    for (var i = 0, l = range.length; i < l; i++) {
 93      versions = versions.filter(function (v) {
 94        return semver.satisfies(v, range[i], options)
 95      })
 96      if (!versions.length) return fail()
 97    }
 98    return success(versions)
 99  }
100  
101  function failInc () {
102    console.error('--inc can only be used on a single version with no range')
103    fail()
104  }
105  
106  function fail () { process.exit(1) }
107  
108  function success () {
109    var compare = reverse ? 'rcompare' : 'compare'
110    versions.sort(function (a, b) {
111      return semver[compare](a, b, options)
112    }).map(function (v) {
113      return semver.clean(v, options)
114    }).map(function (v) {
115      return inc ? semver.inc(v, inc, options, identifier) : v
116    }).forEach(function (v, i, _) { console.log(v) })
117  }
118  
119  function help () {
120    console.log(['SemVer ' + version,
121      '',
122      'A JavaScript implementation of the https://semver.org/ specification',
123      'Copyright Isaac Z. Schlueter',
124      '',
125      'Usage: semver [options] <version> [<version> [...]]',
126      'Prints valid versions sorted by SemVer precedence',
127      '',
128      'Options:',
129      '-r --range <range>',
130      '        Print versions that match the specified range.',
131      '',
132      '-i --increment [<level>]',
133      '        Increment a version by the specified level.  Level can',
134      '        be one of: major, minor, patch, premajor, preminor,',
135      "        prepatch, or prerelease.  Default level is 'patch'.",
136      '        Only one version may be specified.',
137      '',
138      '--preid <identifier>',
139      '        Identifier to be used to prefix premajor, preminor,',
140      '        prepatch or prerelease version increments.',
141      '',
142      '-l --loose',
143      '        Interpret versions and ranges loosely',
144      '',
145      '-p --include-prerelease',
146      '        Always include prerelease versions in range matching',
147      '',
148      '-c --coerce',
149      '        Coerce a string into SemVer if possible',
150      '        (does not imply --loose)',
151      '',
152      'Program exits successfully if any valid version satisfies',
153      'all supplied ranges, and prints all satisfying versions.',
154      '',
155      'If no satisfying versions are found, then exits failure.',
156      '',
157      'Versions are printed in ascending order, so supplying',
158      'multiple versions to the utility will just sort them.'
159    ].join('\n'))
160  }