import { eq , gt , maxSatisfying , minSatisfying , satisfies , valid , } from '@renovatebot/ruby-semver' ; import { logger } from '../../logger' ; import { regEx } from '../../util/regex' ; import type { NewValueConfig , VersioningApi } from '../types' ; import { isSingleOperator , isValidOperator } from './operator' ; import { ltr , parse as parseRange } from './range' ; import { bump , pin , replace } from './strategies' ; import { parse as parseVersion } from './version' ; export const id = 'ruby' ; export const displayName = 'Ruby' ; export const urls = [ 'https://guides.rubygems.org/patterns/' , 'https://bundler.io/v1.5/gemfile.html' , 'https://www.devalot.com/articles/2012/04/gem-versions.html' , ] ; export const supportsRanges = true ; export const supportedRangeStrategies = [ 'bump' , 'extend' , 'pin' , 'replace' ] ; function vtrim < T = unknown > ( version ) { if ( typeof version === 'string' ) { return version . replace ( regEx ( /^v/ ) , '' ) . replace ( regEx ( /('|")/g ) , '' ) ; } return version ; } const equals = ( left , right ) : boolean => eq ( vtrim ( left ) , vtrim ( right ) ) ; const getMajor = ( version ) : number => parseVersion ( vtrim ( version ) ) . major ; const getMinor = ( version ) : number => parseVersion ( vtrim ( version ) ) . minor ; const getPatch = ( version ) : number => parseVersion ( vtrim ( version ) ) . patch ; export const isVersion = ( version ) : boolean => ! ! valid ( vtrim ( version ) ) ; const isGreaterThan = ( left , right ) : boolean => gt ( vtrim ( left ) , vtrim ( right ) ) ; const isLessThanRange = ( version , range ) : boolean => ! ! ltr ( vtrim ( version ) , vtrim ( range ) ) ; const isSingleVersion = ( range ) : boolean => { const { version , operator } = parseRange ( vtrim ( range ) ) ; return operator ? isVersion ( version ) && isSingleOperator ( operator ) : isVersion ( version ) ; } ; function isStable ( version ) { const v = vtrim ( version ) ; return parseVersion ( v ) . prerelease ? false : isVersion ( v ) ; } export const isValid = ( input ) : boolean => input . split ( ',' ) . map ( ( piece ) => vtrim ( piece . trim ( ) ) ) . every ( ( range ) => { const { version , operator } = parseRange ( range ) ; return operator ? isVersion ( version ) && isValidOperator ( operator ) : isVersion ( version ) ; } ) ; export const matches = ( version , range ) : boolean => satisfies ( vtrim ( version ) , vtrim ( range ) ) ; function getSatisfyingVersion ( versions , range ) { return maxSatisfying ( versions . map ( vtrim ) , vtrim ( range ) ) ; } function minSatisfyingVersion ( versions , range ) { return minSatisfying ( versions . map ( vtrim ) , vtrim ( range ) ) ; } const getNewValue = ( { currentValue , rangeStrategy , currentVersion , newVersion , } ) : string | null => { let newValue = null ; if ( isVersion ( currentValue ) ) { newValue = currentValue . startsWith ( 'v' ) ? 'v' + newVersion : newVersion ; } else if ( currentValue . replace ( regEx ( /^=\s*/ ) , '' ) === currentVersion ) { newValue = currentValue . replace ( currentVersion , newVersion ) ; } else { switch ( rangeStrategy ) { case 'update-lockfile' : if ( satisfies ( newVersion , currentValue ) ) { newValue = currentValue ; } else { newValue = getNewValue ( { currentValue , rangeStrategy : 'replace' , currentVersion , newVersion , } ) ; } break ; case 'pin' : newValue = pin ( { to : vtrim ( newVersion ) } ) ; break ; case 'bump' : newValue = bump ( { range : vtrim ( currentValue ) , to : vtrim ( newVersion ) } ) ; break ; case 'auto' : case 'widen' : case 'replace' : newValue = replace ( { range : vtrim ( currentValue ) , to : vtrim ( newVersion ) , } ) ; break ; default : logger . warn ( `Unsupported strategy ${ rangeStrategy }` ) ; } } if ( newValue && regEx ( /^('|")/ ) . exec ( currentValue ) ) { const delimiter = currentValue [ 0 ] ; return newValue . split ( ',' ) . map ( ( element ) => element . replace ( regEx ( `^(?<whitespace>\\s*)` ) , `$<whitespace>${ delimiter }` ) ) . map ( ( element ) => element . replace ( /(?<whitespace>\s*)$/ , `${ delimiter }$<whitespace>` ) ) . join ( ',' ) ; } return newValue ; } ; export const sortVersions = ( left , right ) : number => gt ( vtrim ( left ) , vtrim ( right ) ) ? 1 : - 1 ; export const api = { equals , getMajor , getMinor , getPatch , isCompatible : isVersion , isGreaterThan , isLessThanRange , isSingleVersion , isStable , isValid , isVersion , matches , getSatisfyingVersion , minSatisfyingVersion , getNewValue , sortVersions , } ; export default api ;