summaryrefslogtreecommitdiffstats
path: root/nix-script-diff-generations.sh
blob: 3a60f15f9b46d86e20f68c07f3a04e1662848556 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/usr/bin/env bash

source $(dirname ${BASH_SOURCE[0]})/nix-utils.sh

usage() {
    cat <<EOS
    $(help_synopsis "${BASH_SOURCE[0]}" "[-s | -u] [-n <a..b>] [-h]")

        -s       Use system generation for diffing
        -u       Use system generation for diffing
        -n a..b  Diff these generations
        -h       Show this help and exit

$(help_end)
EOS
}

__SYSTEM=0
__USER=0

GEN_A=
GEN_B=

while getopts "sun:h" OPTION
do
    case $OPTION in

        s)
            stdout "Setting profile: system"
            __SYSTEM=1
            __USER=0
            ;;

        u)
            stdout "Setting profile: user ($USER)"
            __SYSTEM=0
            __USER=1
            ;;

        n)
            GEN_A=$(echo $OPTARG | cut -d "." -f 1)
            GEN_B=$(echo $OPTARG | cut -d "." -f 3)

            stdout "Parsing generations: $OPTARG"
            stdout "Parsing generations: GEN_A: $GEN_A"
            stdout "Parsing generations: GEN_B: $GEN_B"

            if [[ -z "$GEN_A" || -z "$GEN_B" ]]
            then
                stderr "Parsing error for '$OPTARG'"
                usage
                exit 1
            fi
            ;;

        h)
            usage
            exit 1
            ;;
    esac
done

gen_path() {
    if [[ $__SYSTEM -eq 1 ]]
    then
        echo "/nix/var/nix/profiles/system-${1}-link"
    fi

    if [[ $__USER -eq 1 ]]
    then
        echo "/nix/var/nix/profiles/per-user/$USER/profile-${1}-link"
    fi
}

DIR_A=$(gen_path $GEN_A)
DIR_B=$(gen_path $GEN_B)

stdout "VERBOSE         : $VERBOSE"
stdout "SYSTEM          : $__SYSTEM"
stdout "USER            : $__USER"
stdout "Generation A    : $GEN_A"
stdout "from directory  : $DIR_A"
stdout "Generation B    : $GEN_B"
stdout "from directory  : $DIR_B"

if [[ -z "$GEN_A" || -z "$GEN_B" ]]
then
    stderr "No generations"
    exit 1
fi

if [[ ! -e $DIR_A ]]
then
    stderr "Generation $GEN_A does not exist."
    exit 1
fi

if [[ ! -e $DIR_B ]]
then
    stderr "Generation $GEN_B does not exist."
    exit 1
fi

versA=$(mktemp)
stdout "TMP file '$versA' created"
nix-store -qR $DIR_A | sort -t'-' -k 2 > $versA
stdout "Generation packages written for $GEN_A"


versB=$(mktemp)
stdout "TMP file '$versB' created"
nix-store -qR $DIR_B | sort -t'-' -k 2 > $versB
stdout "Generation packages written for $GEN_B"

stdout "Diffing now..."

diff -u $versA $versB | \
    # Select only lines that differ.
    # (no context, no file name, no line number, etc.)
    grep '^[+-]/nix/store' | \
    # Remove the "/nix/store/<hash>" garbage.
    # Add a space instead, to separate the [+-] from the name.
    sed 's:/nix/store/[^-]*-: :' | \
    # sort by name, then prefer '+' over '-'.
    sort -k 2 -k 1,1r

stdout "Removing tmp directories"

rm $versA
rm $versB

stdout "Ready"