git-reset.shon commit cvsserver: fix checkouts with -d <somedir> (cfcbd34)
   1#!/bin/sh
   2
   3USAGE='[--mixed | --soft | --hard]  [<commit-ish>]'
   4. git-sh-setup
   5
   6tmp=${GIT_DIR}/reset.$$
   7trap 'rm -f $tmp-*' 0 1 2 3 15
   8
   9reset_type=--mixed
  10case "$1" in
  11--mixed | --soft | --hard)
  12        reset_type="$1"
  13        shift
  14        ;;
  15-*)
  16        usage ;;
  17esac
  18
  19rev=$(git-rev-parse --verify --default HEAD "$@") || exit
  20rev=$(git-rev-parse --verify $rev^0) || exit
  21
  22# We need to remember the set of paths that _could_ be left
  23# behind before a hard reset, so that we can remove them.
  24if test "$reset_type" = "--hard"
  25then
  26        {
  27                git-ls-files --stage -z
  28                git-rev-parse --verify HEAD 2>/dev/null &&
  29                git-ls-tree -r -z HEAD
  30        } | perl -e '
  31            use strict;
  32            my %seen;
  33            $/ = "\0";
  34            while (<>) {
  35                chomp;
  36                my ($info, $path) = split(/\t/, $_);
  37                next if ($info =~ / tree /);
  38                if (!$seen{$path}) {
  39                        $seen{$path} = 1;
  40                        print "$path\0";
  41                }
  42            }
  43        ' >$tmp-exists
  44fi
  45
  46# Soft reset does not touch the index file nor the working tree
  47# at all, but requires them in a good order.  Other resets reset
  48# the index file to the tree object we are switching to.
  49if test "$reset_type" = "--soft"
  50then
  51        if test -f "$GIT_DIR/MERGE_HEAD" ||
  52           test "" != "$(git-ls-files --unmerged)"
  53        then
  54                die "Cannot do a soft reset in the middle of a merge."
  55        fi
  56else
  57        git-read-tree --reset "$rev" || exit
  58fi
  59
  60# Any resets update HEAD to the head being switched to.
  61if orig=$(git-rev-parse --verify HEAD 2>/dev/null)
  62then
  63        echo "$orig" >"$GIT_DIR/ORIG_HEAD"
  64else
  65        rm -f "$GIT_DIR/ORIG_HEAD"
  66fi
  67git-update-ref HEAD "$rev"
  68
  69case "$reset_type" in
  70--hard )
  71        # Hard reset matches the working tree to that of the tree
  72        # being switched to.
  73        git-checkout-index -f -u -q -a
  74        git-ls-files --cached -z |
  75        perl -e '
  76                use strict;
  77                my (%keep, $fh);
  78                $/ = "\0";
  79                while (<STDIN>) {
  80                        chomp;
  81                        $keep{$_} = 1;
  82                }
  83                open $fh, "<", $ARGV[0]
  84                        or die "cannot open $ARGV[0]";
  85                while (<$fh>) {
  86                        chomp;
  87                        if (! exists $keep{$_}) {
  88                                # it is ok if this fails -- it may already
  89                                # have been culled by checkout-index.
  90                                unlink $_;
  91                                while (s|/[^/]*$||) {
  92                                        rmdir($_) or last;
  93                                }
  94                        }
  95                }
  96        ' $tmp-exists
  97        ;;
  98--soft )
  99        ;; # Nothing else to do
 100--mixed )
 101        # Report what has not been updated.
 102        git-update-index --refresh
 103        ;;
 104esac
 105
 106rm -f "$GIT_DIR/MERGE_HEAD" "$GIT_DIR/rr-cache/MERGE_RR"