chiark / gitweb /
provide a global temporary directory
[topgit.git] / hooks / pre-commit.sh
1 #!/bin/sh
2 # TopGit - A different patch queue manager
3 # (c) Petr Baudis <pasky@suse.cz>  2008
4 # GPLv2
5
6
7 ## Set up all the tg machinery
8
9 set -e
10 tg__include=1
11 tg_util() {
12         . "@bindir@"/tg
13 }
14 tg_util
15
16
17 ## Generally have fun
18
19 # Don't do anything on non-topgit branch
20 if head_=$(git symbolic-ref -q HEAD); then
21         case "$head_" in
22                 refs/heads/*)
23                         head_="${head_#refs/heads/}"
24                         git rev-parse -q --verify "refs/top-bases/$head_" >/dev/null || exit 0;;
25                 *)
26                         exit 0;;
27         esac
28
29 else
30         exit 0;
31 fi
32
33 check_topfile()
34 {
35         local tree file ls_line type size
36         tree=$1
37         file=$2
38
39         ls_line="$(git ls-tree --long "$tree" "$file")" ||
40                 die "Can't ls tree for $file"
41
42         [ -n "$ls_line" ] ||
43                 die "$file is missing"
44
45         # check for type and size
46         set -- $ls_line
47         type=$2
48         size=$4
49
50         # check file is of type blob (file)
51         [ "x$type" = "xblob" ] ||
52                 die "$file is not a file"
53
54         # check for positive size
55         [ "$size" -gt 0 ] ||
56                 die "$file has empty size"
57 }
58
59 tree=$(git write-tree) ||
60         die "Can't write tree"
61
62 check_topfile "$tree" ".topdeps"
63 check_topfile "$tree" ".topmsg"
64
65 check_cycle_name()
66 {
67         [ "$head_" != "$_dep" ] ||
68                 die "TopGit dependencies form a cycle: perpetrator is $_name"
69 }
70
71 # we only need to check newly added deps and for these if a path exists to the
72 # current HEAD
73 git diff --cached "$root_dir/.topdeps" |
74         awk '
75 BEGIN      { in_hunk = 0; }
76 /^@@ /     { in_hunk = 1; }
77 /^\+/      { if (in_hunk == 1) printf("%s\n", substr($0, 2)); }
78 /^[^@ +-]/ { in_hunk = 0; }
79 ' |
80         while read newly_added; do
81                 ref_exists "$newly_added" ||
82                         die "Invalid branch as dependent: $newly_added"
83
84                 # check for self as dep
85                 [ "$head_" != "$newly_added" ] ||
86                         die "Can't have myself as dep"
87
88                 # deps can be non-tgish but we can't run recurse_deps() on them
89                 ref_exists "refs/top-bases/$newly_added" ||
90                         continue
91
92                 # recurse_deps uses dfs but takes the .topdeps from the tree,
93                 # therefore no endless loop in the cycle-check
94                 no_remotes=1 recurse_deps check_cycle_name "$newly_added"
95         done
96
97 # check for repetitions of deps
98 depdir="$(get_temp tg-depdir -d)" ||
99         die "Can't check for multiple occurrences of deps"
100 cat_file "(i):.topdeps" |
101         while read dep; do
102                 [ ! -d "$depdir/$dep" ] ||
103                         die "Multiple occurrences of the same dep: $dep"
104                 mkdir -p "$depdir/$dep" ||
105                         die "Can't check for multiple occurrences of deps"
106         done