Skip to content

Unexpected differences between the new Gemfile.lock and the one generated by the existing Bundler #2

Description

@TaKO8Ki

Gemfile:

gem 'google-cloud-artifact_registry-v1', '~> 0.11.0'

Differences:

-    googleapis-common-protos (1.8.0)
+    googleapis-common-protos (1.7.0)
      google-protobuf (>= 3.18, < 5.a)
-      googleapis-common-protos-types (~> 1.20)
+      googleapis-common-protos-types (~> 1.7)
      grpc (~> 1.41)
    googleapis-common-protos-types (1.20.0)
      google-protobuf (>= 3.18, < 5.a)
    googleauth (1.14.0)
      faraday (>= 1.0, < 3.a)
      google-cloud-env (~> 2.2)
      google-logging-utils (~> 0.1)
      jwt (>= 1.4, < 3.0)
      multi_json (~> 1.11)
      os (>= 0.9, < 2.0)
      signet (>= 0.16, < 2.a)
    grpc (1.71.0)
      google-protobuf (>= 3.25, < 5.0)
      googleapis-common-protos-types (~> 1.0)
-    grpc-google-iam-v1 (1.10.0)
+    grpc-google-iam-v1 (1.11.0)
      google-protobuf (>= 3.18, < 5.a)
-      googleapis-common-protos (~> 1.4)
+      googleapis-common-protos (~> 1.7.0)
Gemfile.lock
GEM
  remote: https://rubygems.org/
  specs:
    addressable (2.8.7)
      public_suffix (>= 2.0.2, < 7.0)
    base64 (0.2.0)
    bigdecimal (3.1.9)
    faraday (2.13.1)
      faraday-net_http (>= 2.0, < 3.5)
      json
      logger
    faraday-net_http (3.4.0)
      net-http (>= 0.5.0)
    faraday-retry (2.3.1)
      faraday (~> 2.0)
    gapic-common (1.0.0)
      faraday (>= 1.9, < 3.a)
      faraday-retry (>= 1.0, < 3.a)
      google-cloud-env (~> 2.2)
      google-logging-utils (~> 0.1)
      google-protobuf (>= 3.25, < 5.a)
      googleapis-common-protos (~> 1.6)
      googleapis-common-protos-types (~> 1.15)
      googleauth (~> 1.12)
      grpc (~> 1.66)
    google-cloud-artifact_registry-v1 (0.11.0)
      gapic-common (>= 0.20.0, < 2.a)
      google-cloud-errors (~> 1.0)
      google-cloud-location (>= 0.4, < 2.a)
      grpc-google-iam-v1 (~> 1.1)
    google-cloud-env (2.3.0)
      base64 (~> 0.2)
      faraday (>= 1.0, < 3.a)
    google-cloud-errors (1.5.0)
    google-cloud-location (1.0.0)
      gapic-common (>= 0.25.0, < 2.a)
      google-cloud-errors (~> 1.0)
    google-logging-utils (0.2.0)
    google-protobuf (4.30.2)
      bigdecimal
      rake (>= 13)
    googleapis-common-protos (1.7.0)
      google-protobuf (>= 3.18, < 5.a)
      googleapis-common-protos-types (~> 1.7)
      grpc (~> 1.41)
    googleapis-common-protos-types (1.20.0)
      google-protobuf (>= 3.18, < 5.a)
    googleauth (1.14.0)
      faraday (>= 1.0, < 3.a)
      google-cloud-env (~> 2.2)
      google-logging-utils (~> 0.1)
      jwt (>= 1.4, < 3.0)
      multi_json (~> 1.11)
      os (>= 0.9, < 2.0)
      signet (>= 0.16, < 2.a)
    grpc (1.71.0)
      google-protobuf (>= 3.25, < 5.0)
      googleapis-common-protos-types (~> 1.0)
    grpc-google-iam-v1 (1.11.0)
      google-protobuf (>= 3.18, < 5.a)
      googleapis-common-protos (~> 1.7.0)
      grpc (~> 1.41)
    json (2.11.3)
    jwt (2.10.1)
      base64
    logger (1.7.0)
    multi_json (1.15.0)
    net-http (0.6.0)
      uri
    os (1.1.4)
    public_suffix (6.0.2)
    rake (13.2.1)
    signet (0.20.0)
      addressable (~> 2.8)
      faraday (>= 0.17.5, < 3.a)
      jwt (>= 1.5, < 3.0)
      multi_json (~> 1.10)
    uri (1.0.3)

PLATFORMS
  ruby

DEPENDENCIES
  google-cloud-artifact_registry-v1 (~> 0.11.0)

BUNDLED WITH
   2.5.22
Gemfile.new.lock
GEM
  remote: https://rubygems.org/
  specs:
    addressable (2.8.7)
      public_suffix (>= 2.0.2, < 7.0)
    base64 (0.2.0)
    bigdecimal (3.1.9)
    faraday (2.13.1)
      faraday-net_http (>= 2.0, < 3.5)
      json
      logger
    faraday-net_http (3.4.0)
      net-http (>= 0.5.0)
    faraday-retry (2.3.1)
      faraday (~> 2.0)
    gapic-common (1.0.0)
      faraday (>= 1.9, < 3.a)
      faraday-retry (>= 1.0, < 3.a)
      google-cloud-env (~> 2.2)
      google-logging-utils (~> 0.1)
      google-protobuf (>= 3.25, < 5.a)
      googleapis-common-protos (~> 1.6)
      googleapis-common-protos-types (~> 1.15)
      googleauth (~> 1.12)
      grpc (~> 1.66)
    google-cloud-artifact_registry-v1 (0.11.0)
      gapic-common (>= 0.20.0, < 2.a)
      google-cloud-errors (~> 1.0)
      google-cloud-location (>= 0.4, < 2.a)
      grpc-google-iam-v1 (~> 1.1)
    google-cloud-env (2.3.0)
      base64 (~> 0.2)
      faraday (>= 1.0, < 3.a)
    google-cloud-errors (1.5.0)
    google-cloud-location (1.0.0)
      gapic-common (>= 0.25.0, < 2.a)
      google-cloud-errors (~> 1.0)
    google-logging-utils (0.2.0)
    google-protobuf (4.30.2)
      bigdecimal
      rake (>= 13)
    googleapis-common-protos (1.8.0)
      google-protobuf (>= 3.18, < 5.a)
      googleapis-common-protos-types (~> 1.20)
      grpc (~> 1.41)
    googleapis-common-protos-types (1.20.0)
      google-protobuf (>= 3.18, < 5.a)
    googleauth (1.14.0)
      faraday (>= 1.0, < 3.a)
      google-cloud-env (~> 2.2)
      google-logging-utils (~> 0.1)
      jwt (>= 1.4, < 3.0)
      multi_json (~> 1.11)
      os (>= 0.9, < 2.0)
      signet (>= 0.16, < 2.a)
    grpc (1.71.0)
      google-protobuf (>= 3.25, < 5.0)
      googleapis-common-protos-types (~> 1.0)
    grpc-google-iam-v1 (1.10.0)
      google-protobuf (>= 3.18, < 5.a)
      googleapis-common-protos (~> 1.4)
      grpc (~> 1.41)
    json (2.11.3)
    jwt (2.10.1)
      base64
    logger (1.7.0)
    multi_json (1.15.0)
    net-http (0.6.0)
      uri
    os (1.1.4)
    public_suffix (6.0.2)
    rake (13.2.1)
    signet (0.20.0)
      addressable (~> 2.8)
      faraday (>= 0.17.5, < 3.a)
      jwt (>= 1.5, < 3.0)
      multi_json (~> 1.10)
    uri (1.0.3)

PLATFORMS
  ruby

DEPENDENCIES
  google-cloud-artifact_registry-v1 (~> 0.11.0)

BUNDLED WITH
   2.5.22

Investigation

In the case that the dependencies include grpc-google-iam-v1 @ 1.8.0, 1.10.0 is selected. However, Ruby bundler selects 1.11.0 with that Gemfile.

The reason why version 1.10.0 is selected when version 1.8.0 is added is probably that PubGrub doesn't simply choose the latest version, but considers the 'flexibility' of the entire dependency graph. The dependency constraint provided by 1.10.0 (googleapis-common-protos > 1.4) is broader than the constraint of 1.11.0 (> 1.7.0), which means it potentially has higher compatibility with other packages.

Test code
>
    #[test]
    fn bundler_like_resolution() {
        struct BundlerOfflineDependencyProvider {
            dependency_provider: OfflineDependencyProvider<String, RichReq>,
        }

        impl BundlerOfflineDependencyProvider {
            fn add_dependencies(
                &mut self,
                package: String,
                version: RubyVersion,
                dependencies: Vec<(String, RichReq)>,
            ) {
                self.dependency_provider
                    .add_dependencies(package, version, dependencies);
            }
        }

        impl DependencyProvider for BundlerOfflineDependencyProvider {
            type P = String;
            type V = <RichReq as VersionSet>::V;
            type VS = RichReq;
            type M = String;

            type Err = Infallible;

            #[inline]
            fn choose_version(
                &self,
                package: &Self::P,
                range: &Self::VS,
            ) -> Result<Option<Self::V>, Infallible> {
                let mut versions = self
                    .dependency_provider
                    .versions(package)
                    .map(|v| v.filter(|v| range.contains(v)).collect::<Vec<_>>())
                    .unwrap_or_default();
                versions.sort_by(|a, b| b.cmp(a));
                if let Some(v) = versions.first() {
                    if package == "grpc-google-iam-v1" {
                        println!(
                            "package: {}, choose_version: {}, versions: {:?}",
                            package, v, versions
                        );
                    }
                    Ok(Some((*v).clone()))
                } else {
                    Ok(None)
                }
                // Ok(
                //     .and_then(|versions| {
                //         versions.keys().rev().find(|v| range.contains(v)).cloned()
                //     }))
            }

            type Priority = (u32, Reverse<usize>);

            #[inline]
            fn prioritize(
                &self,
                package: &Self::P,
                range: &Self::VS,
                package_statistics: &PackageResolutionStatistics,
            ) -> Self::Priority {
                self.dependency_provider
                    .prioritize(package, range, package_statistics)
            }

            #[inline]
            fn get_dependencies(
                &self,
                package: &Self::P,
                version: &Self::V,
            ) -> Result<Dependencies<Self::P, Self::VS, Self::M>, Infallible> {
                self.dependency_provider.get_dependencies(package, version)
            }
        }

        let mut p = BundlerOfflineDependencyProvider {
            dependency_provider: OfflineDependencyProvider::new(),
        };

        /* ------ grpc-google-iam-v1 ------ */
        // 1.10.0
        p.add_dependencies(
            "google-cloud-artifact_registry-v1".into(),
            RubyVersion::parse("0.11.0"),
            vec![
                ("grpc-google-iam-v1".into(), parse_req("~> 1.1", ",").0),
                ("gapic-common".into(), parse_req(">= 0.20.0, < 2.a", ",").0),
            ],
        );

        p.add_dependencies(
            "gapic-common".into(),
            RubyVersion::parse("1.0.0"),
            vec![
                (
                    "googleapis-common-protos-types".into(),
                    parse_req("~> 1.15", ",").0,
                ),
                (
                    "googleapis-common-protos".into(),
                    parse_req("~> 1.6", ",").0,
                ),
            ],
        );

        // 1.11.0

        p.add_dependencies(
            "grpc-google-iam-v1".into(),
            RubyVersion::parse("1.10.0"),
            vec![
                ("google-protobuf".into(), parse_req(">= 3.18, < 5.a", ",").0),
                (
                    "googleapis-common-protos".into(),
                    parse_req("~> 1.4", ",").0,
                ),
                ("grpc".into(), parse_req("~> 1.41", ",").0),
            ],
        );

        p.add_dependencies(
            "grpc-google-iam-v1".into(),
            RubyVersion::parse("1.8.0"),
            vec![
                ("google-protobuf".into(), parse_req(">= 3.18, < 5.a", ",").0),
                (
                    "googleapis-common-protos".into(),
                    parse_req("~> 1.4", ",").0,
                ),
                ("grpc".into(), parse_req("~> 1.41", ",").0),
            ],
        );

        p.add_dependencies(
            "grpc-google-iam-v1".into(),
            RubyVersion::parse("1.11.0"),
            vec![
                ("google-protobuf".into(), parse_req(">= 3.18, < 5.a", ",").0),
                (
                    "googleapis-common-protos".into(),
                    parse_req("~> 1.7.0", ",").0,
                ),
                ("grpc".into(), parse_req("~> 1.41", ",").0),
            ],
        );

        /* ------ googleapis-common-protos ------ */
        p.add_dependencies(
            "googleapis-common-protos".into(),
            RubyVersion::parse("1.7.0"),
            vec![
                ("google-protobuf".into(), parse_req(">= 3.18, < 5.a", ",").0),
                (
                    "googleapis-common-protos-types".into(),
                    parse_req("~> 1.7", ",").0,
                ),
                ("grpc".into(), parse_req("~> 1.41", ",").0),
            ],
        );
        p.add_dependencies(
            "googleapis-common-protos".into(),
            RubyVersion::parse("1.8.0"),
            vec![
                ("google-protobuf".into(), parse_req(">= 3.18, < 5.a", ",").0),
                (
                    "googleapis-common-protos-types".into(),
                    parse_req("~> 1.20", ",").0,
                ),
                ("grpc".into(), parse_req("~> 1.41", ",").0),
            ],
        );

        p.add_dependencies(
            "googleapis-common-protos-types".into(),
            RubyVersion::parse("1.20.0"),
            vec![],
        );
        p.add_dependencies(
            "google-protobuf".into(),
            RubyVersion::parse("4.30.2"),
            vec![],
        );
        p.add_dependencies("grpc".into(), RubyVersion::parse("1.71.0"), vec![]);

        /* ------ root ------ */
        p.add_dependencies(
            "root".into(),
            RubyVersion::parse("0.0.0"),
            vec![(
                "google-cloud-artifact_registry-v1".into(),
                parse_req("~> 0.11.0", ",").0,
            )],
        );

        let sol = resolve(&p, "root".into(), RubyVersion::parse("0.0.0")).unwrap();

        assert_eq!(
            sol.get("grpc-google-iam-v1"),
            Some(&RubyVersion::parse("1.11.0"))
        );
        assert_eq!(
            sol.get("googleapis-common-protos"),
            Some(&RubyVersion::parse("1.7.0"))
        );
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions