-
Notifications
You must be signed in to change notification settings - Fork 8
/
import-ocaml-source.sh
executable file
·155 lines (131 loc) · 4.88 KB
/
import-ocaml-source.sh
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
#!/bin/bash
cd "$(dirname "${BASH_SOURCE[0]}")"
# Script arguments with their default values
repository=https://github.com/ocaml-flambda/flambda-backend
subdirectory=.
old_subdirectory=.
function usage () {
cat <<USAGE
Usage: $0 COMMITISH [REPO [SUBDIRECTORY [OLD_SUBDIRECTORY]]]
Fetch the new compiler sources and patch Merlin to keep Merlin's local copies of
things in sync. By default, this will pull the COMMITISH branch from
<$repository> and look in "$subdirectory/" for the compiler source, but the
branch can be overridden by any commitish (branch, tag, full (not abbreviated!)
commit hash, etc.), the repository can be overridden by any URL, and the
subdirectory can be overriden by any path (including ".").
This attempts to import new files from the compiler by running the
"import_added_ocaml_source_files.sh" script. If that doesn't work, you can also
try making matched pairs of files in this repository with the right names: one
in "upstream/ocaml_flambda/", and one in "src/ocaml". Then running the script
will pull in the named file(s).
The SUBDIRECTORY argument is useful when importing from a repository that buries
the relevant compiler files inside a subdirectory. This used to be the case for
flambda (files were under an "ocaml/" direcotry), although it is no longer the
case. The OLD_SUBDIRECTORY argument is useful for when the directory structure
has changed since the last import.
USAGE
}
function repository-commit () {
if [[ $repository =~ ^https://github.com/(.*) ]]; then
echo "${BASH_REMATCH[1]}@$1"
else
echo "$repository @ $1"
fi
}
case "$1" in
-h|-help|--help|-\?)
usage
exit 0
;;
esac
if [[ $# -gt 0 ]]; then
commitish="$1"
else
usage >&2
exit 1
fi
if [[ $# -le 4 ]]; then
repository="${2-$repository}"
# Although the subdirectory arguments are probably no longer useful, it doesn't hurt
# to keep them around in case they ever are of use.
subdirectory="${3-$subdirectory}"
old_subdirectory="${4-$old_subdirectory}"
else
usage >&2
exit 1
fi
if ! git diff --quiet; then
echo "Working directory must be clean before using this script,"
echo "but currently has the following changes:"
git diff --stat
exit 1
fi
# Used for patch output
old_base_rev="$(cat upstream/ocaml_flambda/base-rev.txt)"
current_head="$(git symbolic-ref --short HEAD)"
# First, add any files that have been added since the last import.
./import-added-ocaml-source-files.sh "$commitish" "$repository" "$subdirectory" "$old_subdirectory"
# Then, fetch the new flambda-backend sources (which include ocaml-jst) and
# copy into upstream/ocaml_flambda
git fetch "$repository" "$commitish"
rev=$(git rev-parse FETCH_HEAD)
cd upstream/ocaml_flambda
echo $rev > base-rev.txt
for file in $(git ls-tree --name-only -r HEAD | grep -v base-rev.txt); do
if [[ "$subdirectory" = "." ]]; then
git_file="$file"
else
git_file="$subdirectory/$file"
fi
git show "FETCH_HEAD:$git_file" > "$file"
done
git add -u .
cd ../..
git commit -m "Import ocaml sources for $(repository-commit "$(git describe --always $rev)")"
# Annotations for diff3 regions; "@" would be more natural than ":" but confuses
# smerge-mode's highlighting
short_ocaml_repo="${repository#https://github.com/}"
old_marker="janestreet/merlin-jst:$current_head"
parent_marker="$short_ocaml_repo:$old_base_rev"
new_marker="$short_ocaml_repo:$commitish"
# Then patch src/ocaml using the changes you just imported
for file in $(git diff --no-ext-diff --name-only HEAD^ HEAD); do
base=${file#upstream/ocaml_flambda/}
case $base in
# If you add new files here, you need to apply the full diff manually once,
# otherwise the merge won't pick up on old changes!
# Renamed files
parsing/lexer.mll) tgt=preprocess/lexer_raw.mll;;
parsing/parser.mly) tgt=preprocess/parser_raw.mly;;
# Merlin moves the modules it depends on from this directory into `typing/`
# (as of the time of writing, that's `Cmi_format` and `Cmt_format`)
file_formats/*) tgt=${base/#file_formats/typing};;
# We can't have these modules in `utils/`, it breaks Merlin's dependency
# structure
utils/compilation_unit.ml*|utils/import_info.ml*)
tgt=${base/#utils/typing};;
# We have to inspect these files by hand, we only care about a subset of the
# changes
utils/clflags.ml*|utils/config.ml*)
printf '\e[7mIgnoring changes to %s, inspect it manually.\e[0m\n' "$base"
continue;;
# Most cases are simple
*) tgt=$base;;
esac
tgt=src/ocaml/$tgt
# Not all files are necessary
if [ ! -e $tgt ]; then continue; fi
err=$(patch --merge=diff3 $tgt <(git diff --no-ext-diff HEAD^ HEAD -- $file))
# ignore patch output if it worked
if [ $? = 0 ]; then
git add -u $tgt
else
sed -i \
-e 's!^<<<<<<<$!& '"$old_marker"'!' \
-e 's!^|||||||$!& '"$parent_marker"'!' \
-e 's!^>>>>>>>$!& '"$new_marker"'!' \
$tgt
echo "$err"
fi
rm -f $tgt.orig
done