summary refs log tree commit diff
path: root/pkgs/applications/version-management/git-and-tools/git/default.nix
blob: 9396c6cd99c4d408d19c998206a9d61eb57b104c (plain) (blame)
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
{ fetchurl, stdenv, buildPackages
, curl, openssl, zlib, expat, perlPackages, python3, gettext, cpio
, gnugrep, gnused, gawk, coreutils # needed at runtime by git-filter-branch etc
, openssh, pcre2
, asciidoc, texinfo, xmlto, docbook2x, docbook_xsl, docbook_xml_dtd_45
, libxslt, tcl, tk, makeWrapper, libiconv
, svnSupport, subversionClient, perlLibs, smtpPerlLibs
, perlSupport ? true
, guiSupport
, withManual ? true
, pythonSupport ? true
, withpcre2 ? true
, sendEmailSupport
, darwin
, withLibsecret ? false
, pkgconfig, glib, libsecret
, gzip # needed at runtime by gitweb.cgi
}:

assert sendEmailSupport -> perlSupport;
assert svnSupport -> perlSupport;

let
  version = "2.25.1";
  svn = subversionClient.override { perlBindings = perlSupport; };

  gitwebPerlLibs = with perlPackages; [ CGI HTMLParser CGIFast FCGI FCGIProcManager HTMLTagCloud ];
in

stdenv.mkDerivation {
  pname = "git";
  inherit version;

  src = fetchurl {
    url = "https://www.kernel.org/pub/software/scm/git/git-${version}.tar.xz";
    sha256 = "09lzwa183nblr6l8ib35g2xrjf9wm9yhk3szfvyzkwivdv69c9r2";
  };

  outputs = [ "out" ];

  hardeningDisable = [ "format" ];

  enableParallelBuilding = true;

  ## Patch

  patches = [
    ./docbook2texi.patch
    ./git-sh-i18n.patch
    ./ssh-path.patch
    ./git-send-email-honor-PATH.patch
    ./installCheck-path.patch
  ];

  postPatch = ''
    for x in connect.c git-gui/lib/remote_add.tcl ; do
      substituteInPlace "$x" \
        --subst-var-by ssh "${openssh}/bin/ssh"
    done

    # Fix references to gettext introduced by ./git-sh-i18n.patch
    substituteInPlace git-sh-i18n.sh \
        --subst-var-by gettext ${gettext}
  '';

  nativeBuildInputs = [ gettext perlPackages.perl ]
    ++ stdenv.lib.optionals withManual [ asciidoc texinfo xmlto docbook2x
         docbook_xsl docbook_xml_dtd_45 libxslt ];
  buildInputs = [curl openssl zlib expat cpio makeWrapper libiconv]
    ++ stdenv.lib.optionals perlSupport [ perlPackages.perl ]
    ++ stdenv.lib.optionals guiSupport [tcl tk]
    ++ stdenv.lib.optionals withpcre2 [ pcre2 ]
    ++ stdenv.lib.optionals stdenv.isDarwin [ darwin.Security ]
    ++ stdenv.lib.optionals withLibsecret [ pkgconfig glib libsecret ];

  # required to support pthread_cancel()
  NIX_LDFLAGS = stdenv.lib.optionalString (!stdenv.cc.isClang) "-lgcc_s"
              + stdenv.lib.optionalString (stdenv.isFreeBSD) "-lthr";

  configureFlags = stdenv.lib.optionals (stdenv.buildPlatform != stdenv.hostPlatform) [
    "ac_cv_fread_reads_directories=yes"
    "ac_cv_snprintf_returns_bogus=no"
  ];

  preBuild = ''
    makeFlagsArray+=( perllibdir=$out/$(perl -MConfig -wle 'print substr $Config{installsitelib}, 1 + length $Config{siteprefixexp}') )
  '';

  makeFlags = [
    "prefix=\${out}"
    "SHELL_PATH=${stdenv.shell}"
  ]
  ++ (if perlSupport then ["PERL_PATH=${perlPackages.perl}/bin/perl"] else ["NO_PERL=1"])
  ++ (if pythonSupport then ["PYTHON_PATH=${python3}/bin/python"] else ["NO_PYTHON=1"])
  ++ stdenv.lib.optionals stdenv.isSunOS ["INSTALL=install" "NO_INET_NTOP=" "NO_INET_PTON="]
  ++ (if stdenv.isDarwin then ["NO_APPLE_COMMON_CRYPTO=1"] else ["sysconfdir=/etc"])
  ++ stdenv.lib.optionals stdenv.hostPlatform.isMusl ["NO_SYS_POLL_H=1" "NO_GETTEXT=YesPlease"]
  ++ stdenv.lib.optional withpcre2 "USE_LIBPCRE2=1";


  postBuild = ''
    make -C contrib/subtree
  '' + (stdenv.lib.optionalString perlSupport ''
    make -C contrib/diff-highlight
  '') + (stdenv.lib.optionalString stdenv.isDarwin ''
    make -C contrib/credential/osxkeychain
  '') + (stdenv.lib.optionalString withLibsecret ''
    make -C contrib/credential/libsecret
  '');


  ## Install

  # WARNING: Do not `rm` or `mv` files from the source tree; use `cp` instead.
  #          We need many of these files during the installCheckPhase.

  installFlags = [ "NO_INSTALL_HARDLINKS=1" ];

  preInstall = (stdenv.lib.optionalString stdenv.isDarwin ''
    mkdir -p $out/bin
    ln -s $out/share/git/contrib/credential/osxkeychain/git-credential-osxkeychain $out/bin/
    rm -f $PWD/contrib/credential/osxkeychain/git-credential-osxkeychain.o
  '') + (stdenv.lib.optionalString withLibsecret ''
    mkdir -p $out/bin
    ln -s $out/share/git/contrib/credential/libsecret/git-credential-libsecret $out/bin/
    rm -f $PWD/contrib/credential/libsecret/git-credential-libsecret.o
  '');

  postInstall =
    ''
      notSupported() {
        unlink $1 || true
      }

      # Install git-subtree.
      make -C contrib/subtree install ${stdenv.lib.optionalString withManual "install-doc"}
      rm -rf contrib/subtree

      # Install contrib stuff.
      mkdir -p $out/share/git
      cp -a contrib $out/share/git/
      mkdir -p $out/share/emacs/site-lisp
      ln -s "$out/share/git/contrib/emacs/"*.el $out/share/emacs/site-lisp/
      mkdir -p $out/share/bash-completion/completions
      ln -s $out/share/git/contrib/completion/git-completion.bash $out/share/bash-completion/completions/git
      mkdir -p $out/etc/bash_completion.d
      ln -s $out/share/git/contrib/completion/git-prompt.sh $out/etc/bash_completion.d/
      mkdir -p $out/share/zsh/site-functions
      ln -s $out/share/git/contrib/completion/git-completion.zsh $out/share/zsh/site-functions/_git

      # Patch the zsh completion script so it can find the Bash completion script.
      sed -i -e "/locations=(/a \${"\t\t"}'$out/share/git/contrib/completion/git-completion.bash'" \
        $out/share/git/contrib/completion/git-completion.zsh

      # grep is a runtime dependency, need to patch so that it's found
      substituteInPlace $out/libexec/git-core/git-sh-setup \
          --replace ' grep' ' ${gnugrep}/bin/grep' \
          --replace ' egrep' ' ${gnugrep}/bin/egrep'

      # Fix references to the perl, sed, awk and various coreutil binaries used by
      # shell scripts that git calls (e.g. filter-branch)
      SCRIPT="$(cat <<'EOS'
        BEGIN{
          @a=(
            '${gnugrep}/bin/grep', '${gnused}/bin/sed', '${gawk}/bin/awk',
            '${coreutils}/bin/cut', '${coreutils}/bin/basename', '${coreutils}/bin/dirname',
            '${coreutils}/bin/wc', '${coreutils}/bin/tr'
            ${stdenv.lib.optionalString perlSupport ", '${perlPackages.perl}/bin/perl'"}
          );
        }
        foreach $c (@a) {
          $n=(split("/", $c))[-1];
          s|(?<=[^#][^/.-])\b''${n}(?=\s)|''${c}|g
        }
      EOS
      )"
      perl -0777 -i -pe "$SCRIPT" \
        $out/libexec/git-core/git-{sh-setup,filter-branch,merge-octopus,mergetool,quiltimport,request-pull,submodule,subtree,web--browse}


      # Also put git-http-backend into $PATH, so that we can use smart
      # HTTP(s) transports for pushing
      ln -s $out/libexec/git-core/git-http-backend $out/bin/git-http-backend
    '' + stdenv.lib.optionalString perlSupport ''
      # wrap perl commands
      makeWrapper "$out/share/git/contrib/credential/netrc/git-credential-netrc" $out/bin/git-credential-netrc \
                  --set PERL5LIB   "$out/${perlPackages.perl.libPrefix}:${perlPackages.makePerlPath perlLibs}"
      wrapProgram $out/libexec/git-core/git-cvsimport \
                  --set GITPERLLIB "$out/${perlPackages.perl.libPrefix}:${perlPackages.makePerlPath perlLibs}"
      wrapProgram $out/libexec/git-core/git-add--interactive \
                  --set GITPERLLIB "$out/${perlPackages.perl.libPrefix}:${perlPackages.makePerlPath perlLibs}"
      wrapProgram $out/libexec/git-core/git-archimport \
                  --set GITPERLLIB "$out/${perlPackages.perl.libPrefix}:${perlPackages.makePerlPath perlLibs}"
      wrapProgram $out/libexec/git-core/git-instaweb \
                  --set GITPERLLIB "$out/${perlPackages.perl.libPrefix}:${perlPackages.makePerlPath perlLibs}"
      wrapProgram $out/libexec/git-core/git-cvsexportcommit \
                  --set GITPERLLIB "$out/${perlPackages.perl.libPrefix}:${perlPackages.makePerlPath perlLibs}"

      # gzip (and optionally bzip2, xz, zip) are runtime dependencies for
      # gitweb.cgi, need to patch so that it's found
      sed -i -e "s|'compressor' => \['gzip'|'compressor' => ['${gzip}/bin/gzip'|" \
          $out/share/gitweb/gitweb.cgi
      # Give access to CGI.pm and friends (was removed from perl core in 5.22)
      for p in ${stdenv.lib.concatStringsSep " " gitwebPerlLibs}; do
          sed -i -e "/use CGI /i use lib \"$p/${perlPackages.perl.libPrefix}\";" \
              "$out/share/gitweb/gitweb.cgi"
      done
    ''

   + (if svnSupport then ''
        # wrap git-svn
        wrapProgram $out/libexec/git-core/git-svn                                                                                \
                     --set GITPERLLIB "$out/${perlPackages.perl.libPrefix}:${perlPackages.makePerlPath (perlLibs ++ [svn.out])}" \
                     --prefix PATH : "${svn.out}/bin" ''
       else '' # replace git-svn by notification script
        notSupported $out/libexec/git-core/git-svn
     '')

   + (if sendEmailSupport then ''
        # wrap git-send-email
        wrapProgram $out/libexec/git-core/git-send-email \
                     --set GITPERLLIB "$out/${perlPackages.perl.libPrefix}:${perlPackages.makePerlPath smtpPerlLibs}"
      '' else ''
        # replace git-send-email by notification script
        notSupported $out/libexec/git-core/git-send-email
      '')

   + stdenv.lib.optionalString withManual ''# Install man pages and Info manual
       make -j $NIX_BUILD_CORES -l $NIX_BUILD_CORES PERL_PATH="${buildPackages.perl}/bin/perl" cmd-list.made install install-info \
         -C Documentation ''

   + (if guiSupport then ''
       # Wrap Tcl/Tk programs
       for prog in bin/gitk libexec/git-core/{git-gui,git-citool,git-gui--askpass}; do
         sed -i -e "s|exec 'wish'|exec '${tk}/bin/wish'|g" \
                -e "s|exec wish|exec '${tk}/bin/wish'|g" \
                -e "s|exec \"[^\"]*/MacOS/Wish\"|exec '${tk}/bin/wish'|g" \
                "$out/$prog"
       done
       ln -s $out/share/git/contrib/completion/git-completion.bash $out/share/bash-completion/completions/gitk
     '' else ''
       # Don't wrap Tcl/Tk, replace them by notification scripts
       for prog in bin/gitk libexec/git-core/git-gui; do
         notSupported "$out/$prog"
       done
     '')
   + stdenv.lib.optionalString stdenv.isDarwin ''
    # enable git-credential-osxkeychain by default if darwin
    cat > $out/etc/gitconfig << EOF
    [credential]
      helper = osxkeychain
    EOF
  '';


  ## InstallCheck

  doCheck = false;
  doInstallCheck = true;

  installCheckTarget = "test";

  # see also installCheckFlagsArray
  installCheckFlags = [
    "DEFAULT_TEST_TARGET=prove"
    "PERL_PATH=${buildPackages.perl}/bin/perl"
  ];

  preInstallCheck = ''
    installCheckFlagsArray+=(
      GIT_PROVE_OPTS="--jobs $NIX_BUILD_CORES --failures --state=failed,save"
      GIT_TEST_INSTALLED=$out/bin
      ${stdenv.lib.optionalString (!svnSupport) "NO_SVN_TESTS=y"}
    )

    function disable_test {
      local test=$1 pattern=$2
      if [ $# -eq 1 ]; then
        mv t/{,skip-}$test.sh || true
      else
        sed -i t/$test.sh \
          -e "/^ *test_expect_.*$pattern/,/^ *' *\$/{s/^/#/}"
      fi
    }

    # Shared permissions are forbidden in sandbox builds.
    disable_test t0001-init shared
    disable_test t1301-shared-repo

    # Our patched gettext never fallbacks
    disable_test t0201-gettext-fallbacks

    ${stdenv.lib.optionalString (!sendEmailSupport) ''
      # Disable sendmail tests
      disable_test t9001-send-email
    ''}

    # XXX: I failed to understand why this one fails.
    # Could someone try to re-enable it on the next release ?
    # Tested to fail: 2.18.0 and 2.19.0
    disable_test t1700-split-index "null sha1"

    # Tested to fail: 2.18.0
    disable_test t9902-completion "sourcing the completion script clears cached --options"

    ${stdenv.lib.optionalString (!perlSupport) ''
      # request-pull is a Bash script that invokes Perl, so it is not available
      # when NO_PERL=1, and the test should be skipped, but the test suite does
      # not check for the Perl prerequisite.
      disable_test t5150-request-pull
    ''}
  '' + stdenv.lib.optionalString stdenv.isDarwin ''
    # XXX: Some tests added in 2.24.0 fail.
    # Please try to re-enable on the next release.
    disable_test t7816-grep-binary-pattern
  '' + stdenv.lib.optionalString stdenv.hostPlatform.isMusl ''
    # Test fails (as of 2.17.0, musl 1.1.19)
    disable_test t3900-i18n-commit
    # Fails largely due to assumptions about BOM
    # Tested to fail: 2.18.0
    disable_test t0028-working-tree-encoding
  '';

  stripDebugList = [ "lib" "libexec" "bin" "share/git/contrib/credential/libsecret" ];


  meta = {
    homepage = https://git-scm.com/;
    description = "Distributed version control system";
    license = stdenv.lib.licenses.gpl2;

    longDescription = ''
      Git, a popular distributed version control system designed to
      handle very large projects with speed and efficiency.
    '';

    platforms = stdenv.lib.platforms.all;
    maintainers = with stdenv.lib.maintainers; [ peti the-kenny wmertens globin ];
  };
}