-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfbsd-r2g
executable file
·115 lines (104 loc) · 3.23 KB
/
fbsd-r2g
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
#! /bin/sh
#
# fbsd-r2g
#
# This script converts a FreeBSD -r<nnn> SVN revision to
# a git commit ID, using the git repository stored in
# git://github.com/freebsd/freebsd.git
#
# Note: you must configure your copy of this repository
# with an additional `fetch =` line, e.g.:
#
# fetch = +refs/notes/*:refs/notes/origin/*
#
# Currently, refs/notes/origin/commits is hardcoded into this
# script.
usage()
{
echo "$0 revision [ ... ]"
}
warn()
{
printf '%s\n' "$@" 1>&2
}
die()
{
echo "fatal: $@" 1>&2
exit 1
}
# We read all the notes from the topmost note's tree
# (as found by the git rev-parse below). This tree
# contains files almost named "badf00dc0ffeedeadc0dedeadbeef..."
# whose contents are the notes for commit "badf00dc0ffee...".
# However, for performance reasons, git notes sub-tree the
# note, so that the actual file name is more like "ba/df/00/dc0ffee...".
#
# Normally, "git log" uses core.notesRef (which you would
# set to refs/notes/origin/commits) to look for a file whose
# name matches a commit, e.g., if it's about to show you commit
# badf00dc0ffee... it checks for this file in the tree pointed
# to by the ref in core.notesRef. It knows to keep going if
# what it finds is a sub-tree, so if it sees a tree named "ba",
# it takes that off and looks for "df00dc0ffee...", and so on.
#
# We can do a similar job using "git grep", which can search
# a tree. (Technically we could just point git grep at the commit
# and it would find the tree, but this makes sure the tree exists
# before we even try.) We know that FreeBSD commits store a
# note of the form "svn path=...; revision=..." so we grep for
# the revision= part.
findrev()
{
local rev path nraw nvalid status
# remove leading "r" or "-r" if present; argument will
# be svn-style r12345 or -r12345, and we just want the rev.
rev="$1"
case "$rev" in
-r*) rev=${rev#-r};;
r*) rev=${rev#r};;
esac
# This finds lines such as:
#
# $TREE:$path/$to/$file:svn path=/head/; revision=352558
#
# The $TREE part is our $TREE argument, hence not useful.
# We really just need the $path/to/file part -- e.g.,
# 57/bb/1dff57ee60eac5aed02043a3903ccce141bc -- within
# that tree. Stripping out the slashes gives us the commit
# hash ID for the right commit.
git grep -e "revision=${rev}$" $TREE > $TF
# We might not find any notes. Even if we do, some
# svn commits get a note, then wind up not in the local
# repository.
nraw=0
nvalid=0
while IFS=: read rev path matched; do
path=$(echo $path | sed s,/,,g)
nraw=$((nraw + 1))
# Note: git rev-parse always believes a raw hash
# is valid, so test with ^{commit}.
if git rev-parse -q --verify $path^{commit} >/dev/null; then
nvalid=$((nvalid + 1))
status=""
else
status=" -- NOT IN REPO"
fi
echo "commit $path ($matched)$status"
done < $TF
# not sure which test to use here, let's use nvalid for now
#test $nraw -gt 0
test $nvalid -gt 0
}
TF=$(mktemp -t findrev) || die "cannot make temporary file"
trap "rm -f $TF; exit" 0 1 2 3 15
TREE=$(git rev-parse refs/notes/origin/commits^{tree} 2>/dev/null) ||
die "no refs/notes/origin/commits tree - are you in a freebsd repo?"
case $# in
0) usage; exit 1;;
*) ;;
esac
status=0
for rev do
findrev "$rev" || { warn "$rev: not found"; status=1; }
done
exit $status