Get revision with binary caches closest to certain revision

Hello. I’v debugging Zoom black video on NixOS · Issue #41203 · NixOS/nixpkgs · GitHub, and for this I’d like to check NixOS revision before DBus upgrade, and after.

Here is DBus upgrade commit dbus: 1.10.24 -> 1.12.6 · NixOS/nixpkgs@e497597 · GitHub

How can I get the nixpkgs-channel latest release, that has binary caches, but doesn’t include the abovementioned commit? Similar, how can I get the first release of nixpkgs-channels that uses the abovementioned release?

You can use `-I “nixpkgs=/locally/cloned/repo” with any of the Nix commands. Just clone nixpkgs and use the regular git to test the various commits

Yeah, but full system rebuild lasts for 6 hours on my laptop. That’s why I’d like to bisect first with binary caches.

Maybe https://channels.nix.gsc.io/nixos-18.03/history will help you.

Frank

1 Like

You rock! Made a script for this:

#!/usr/bin/env bash
set -euo pipefail
rev="$1"
prev=()
channels="$(curl -s https://channels.nix.gsc.io/nixos-unstable/history)"
(
    cd ~/dev/nixpkgs
    echo -e "$channels" | while read -a line; do
        echo -n .
        if [ -n "$(git rev-list $rev..${line[0]})" -a -z "$(git rev-list ${line[0]}..$rev)" ]; then
            echo
            echo "${prev[0]}, dated $(date -d @${prev[1]}) is last revision, that doesn't contain requested commit"
            echo "${line[0]}, dated $(date -d @${line[1]}) is first revision, that contains requested commit"
            exit 1
        fi
        prev=("${line[@]}")
    done && echo "Your commit doesn't belong to nixos-unstable"
)
1 Like

Is this still the recommended solution? I’m running into a similar problem debugging libuv/luarocks.

This was incredibly helpful, thanks! Here’s a refactored version that uses a binary search rather a linear search:

#!/usr/bin/env bash

set -euo pipefail

cd ~/Development/code/nixpkgs

commit="$1"
channels=(
    $(curl -s https://channels.nix.gsc.io/nixos-unstable/history | cut -d ' ' -f 1)
)
min=0
max=$(( ${#channels[@]} - 1 ))

while (( min < max ))
do
    echo -n .

    mid=$(( (max + min) / 2 ))
    rev=${channels[$mid]}

    if git merge-base --is-ancestor "$commit" "$rev"
    then
        max=$mid
    else
        min=$(( mid + 1 ))
    fi
done
echo

if (( min == max ))
then
    rev=${channels[$min]}

    if git merge-base --is-ancestor "$commit" "$rev"
    then
        if (( min > 0 ))
        then
            echo "${channels[$(( min - 1 ))]} is the last revision that doesn't contain $commit"
        fi
        echo "$rev is the first revision that contains $commit"

        exit 0
    fi
fi

echo "Commit not found in nixos-unstable" >&2
exit 1