semver.js 4.6 KB

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