Skip to content
Snippets Groups Projects
Select Git revision
  • 0803b46d23710c11c7f07bdedb3d6f4a4b3594f4
  • main default protected
  • renovate/main-renovatebot-github-action-43.x
  • next
  • feat/gnupg
  • fix/36615b-branch-reuse-no-cache
  • renovate/main-redis-5.x
  • chore/punycode
  • refactor/pin-new-value
  • feat/36219--git-x509-signing
  • feat/structured-logger
  • hotfix/39.264.1
  • feat/skip-dangling
  • gh-readonly-queue/next/pr-36034-7a061c4ca1024a19e2c295d773d9642625d1c2be
  • hotfix/39.238.3
  • refactor/gitlab-auto-approve
  • feat/template-strings
  • gh-readonly-queue/next/pr-35654-137d934242c784e0c45d4b957362214f0eade1d7
  • fix/32307-global-extends-merging
  • fix/32307-global-extends-repositories
  • gh-readonly-queue/next/pr-35009-046ebf7cb84ab859f7fefceb5fa53a54ce9736f8
  • 41.45.0
  • 41.44.0
  • 41.43.7
  • 41.43.6
  • 41.43.5
  • 41.43.4
  • 41.43.3
  • 41.43.2
  • 41.43.1
  • 41.43.0
  • 41.42.12
  • 41.42.11
  • 41.42.10
  • 41.42.9
  • 41.42.8
  • 41.42.7
  • 41.42.6
  • 41.42.5
  • 41.42.4
  • 41.42.3
41 results

version.ts

Blame
  • version.ts 3.99 KiB
    import { eq, major, minor, patch, prerelease } from '@renovatebot/ruby-semver';
    import {
      SegmentElement,
      create,
    } from '@renovatebot/ruby-semver/dist/ruby/version.js';
    import { regEx } from '../../../util/regex';
    
    interface RubyVersion {
      major: number;
      minor: number;
      patch: number;
      prerelease: string[] | null;
    }
    
    function releaseSegments(version: string): SegmentElement[] {
      const v = create(version);
      if (v) {
        return v.release().getSegments();
      }
      /* istanbul ignore next */
      return [];
    }
    
    const parse = (version: string): RubyVersion => ({
      major: major(version),
      minor: minor(version),
      patch: patch(version),
      prerelease: prerelease(version),
    });
    
    const floor = (version: string): string => {
      const segments = releaseSegments(version);
      if (segments.length <= 1) {
        // '~> 2' is equivalent to '~> 2.0', thus no need to floor
        return segments.join('.');
      }
      return [...segments.slice(0, -1), 0].join('.');
    };
    
    const adapt = (left: string, right: string): string =>
      left.split('.').slice(0, right.split('.').length).join('.');
    
    const trimZeroes = (version: string): string => {
      const segments = version.split('.');
      while (segments.length > 0 && segments[segments.length - 1] === '0') {
        segments.pop();
      }
      return segments.join('.');
    };
    
    // Returns the upper bound of `~>` operator.
    const pgteUpperBound = (version: string): string => {
      const segments = releaseSegments(version);
      if (segments.length > 1) {
        segments.pop();
      }
      return incrementLastSegment(segments.join('.'));
    };
    
    // istanbul ignore next
    const incrementLastSegment = (version: string): string => {
      const segments = releaseSegments(version);
      const nextLast = parseInt(segments.pop() as string, 10) + 1;
    
      return [...segments, nextLast].join('.');
    };
    
    // istanbul ignore next
    const incrementMajor = (
      maj: number,
      min: number,
      ptch: number,
      pre: string[],
    ): number => (min === 0 || ptch === 0 || pre.length === 0 ? maj + 1 : maj);
    
    // istanbul ignore next
    const incrementMinor = (min: number, ptch: number, pre: string[]): number =>
      ptch === 0 || pre.length === 0 ? min + 1 : min;
    
    // istanbul ignore next
    const incrementPatch = (ptch: number, pre: string[]): number =>
      pre.length === 0 ? ptch + 1 : ptch;
    
    // istanbul ignore next
    const increment = (from: string, to: string): string => {
      const parsed = parse(from);
      const { major: maj, prerelease: pre } = parsed;
      let { minor: min, patch: ptch } = parsed;
      min = min || 0;
      ptch = ptch || 0;
    
      let nextVersion: string;
      const adapted = adapt(to, from);
      if (eq(from, adapted)) {
        return incrementLastSegment(from);
      }
    
      const isStable = (x: string): boolean => regEx(/^[0-9.-/]+$/).test(x);
      if (major(from) !== major(adapted)) {
        nextVersion = [incrementMajor(maj, min, ptch, pre ?? []), 0, 0].join('.');
      } else if (minor(from) !== minor(adapted)) {
        nextVersion = [maj, incrementMinor(min, ptch, pre ?? []), 0].join('.');
      } else if (patch(from) !== patch(adapted)) {
        nextVersion = [maj, min, incrementPatch(ptch, pre ?? [])].join('.');
      } else if (isStable(from) && isStable(adapted)) {
        nextVersion = [maj, min, incrementPatch(ptch, pre ?? [])].join('.');
      } else {
        nextVersion = [maj, min, ptch].join('.');
      }
    
      return increment(nextVersion, to);
    };
    
    // istanbul ignore next
    const decrement = (version: string): string => {
      const segments = releaseSegments(version);
      const nextSegments = segments
        .reverse()
        .reduce(
          (
            accumulator: number[],
            segment: SegmentElement,
            index: number,
          ): number[] => {
            if (index === 0) {
              return [(segment as number) - 1];
            }
    
            if (accumulator[index - 1] === -1) {
              return [
                ...accumulator.slice(0, index - 1),
                0,
                (segment as number) - 1,
              ];
            }
    
            return [...accumulator, segment as number];
          },
          [],
        );
    
      return nextSegments.reverse().join('.');
    };
    
    export {
      parse,
      adapt,
      floor,
      trimZeroes,
      pgteUpperBound,
      increment,
      decrement,
    };