Skip to content

Commit e28fcd7

Browse files
jack-pappasKevinRansom
authored andcommitted
Implement script for diffing fsharp repos. (dotnet#2597)
Implement a shell script wrapping ``git diff`` to diff the fsharp/fsharp and Microsoft/visualfsharp repositories and produce a patch. The patch is useful when looking for changes which need to be synced (manually) between the two repositories, and for changes in projects or build scripts that may result in behaviorial differences between code compiled from the different repos.
1 parent 1c944df commit e28fcd7

File tree

2 files changed

+119
-0
lines changed

2 files changed

+119
-0
lines changed

.gitignore

+7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1+
# Downloaded packages and build tools.
2+
/lkg
13
/packages
24
/Tools
5+
6+
# Patches that may have been generated by scripts.
7+
# (These aren't generally useful to commit directly; if anything, they should be applied.)
8+
scripts/*.patch
9+
310
/src/*.userprefs
411
/src/fsharp/FSStrings.resources
512
/src/fsharp/FSharp.Build/*.resx

scripts/diff-fsharp-repos.sh

+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
#!/bin/sh
2+
# Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
# This script generates a patch by comparing the contents of the fsharp/fsharp
5+
# and Microsoft/visualfsharp Github repositories. The resulting patch can be applied,
6+
# if desired, to one of the repositories to synchronize changes in one direction;
7+
# CAUTION MUST BE TAKEN though, since this script generates the patch in a way that
8+
# ignores any ordering of commits in the repos -- so it could also end up reverting
9+
# changes that were actually needed.
10+
# The produced patch is primarily useful for examining differences between two repos
11+
# and making it easier to submit targeted PRs to manually synchronize changes.
12+
13+
# Helper function to clean up after we're done (or if there's an error).
14+
cleanup () {
15+
# Leave the working directory, then delete it.
16+
{ popd && rm -rf "$tmpdir"; } || printf "Unable to clean up temp directory '%s'\n" "$tmpdir"
17+
}
18+
19+
# Helper function to print an error message and exit with a non-zero error code.
20+
failwith () {
21+
printf "Error: %s\n" "$1" >&2
22+
cleanup
23+
exit 1
24+
}
25+
26+
# Delete the .git folder from a folder containing an extracted/cloned repository.
27+
remove_git () {
28+
{ pushd "$1" && rm -rf .git && popd; } || \
29+
{ printf "Error: Couldn't remove .git from '%s'\n" "$1"; cleanup_error; }
30+
}
31+
32+
# Delete "don't care" files from a folder containing an extracted/cloned repository.
33+
# These are files with known differences between the two repos, but where we don't care
34+
# about those differences for the purposes of generating a patch.
35+
remove_irrelevant_files () {
36+
if pushd "$1"; then
37+
# TODO: Use 'for in _ do' syntax here instead? Maybe read the list from a separate text file?
38+
# If any of the files in here can't be removed, ignore the failure and keep going.
39+
rm .travis.yml
40+
rm CHANGELOG.md
41+
rm CONTRIBUTING.md
42+
rm README.md
43+
44+
popd
45+
fi
46+
}
47+
48+
# Options for controlling the behavior of this script.
49+
tmpdir="diff_tmp" # name of temp folder to create and work in
50+
fetch_source_by_cloning=1 # git diff doesn't seem to like curl+tar, so clone with git for now.
51+
github_org1="fsharp"
52+
github_repo1="fsharp"
53+
github_org2="Microsoft"
54+
github_repo2="visualfsharp"
55+
repo_dir1="${github_org1}_${github_repo1}"
56+
repo_dir2="${github_org2}_${github_repo2}"
57+
include_all_changes=0 # If set to 1, file additions/deletions will also be included in the patch.
58+
patch_path="../${github_repo1}-${github_repo2}.patch"
59+
60+
# Create a temporary directory to work in.
61+
if ! mkdir "$tmpdir"; then
62+
printf "Unable to create temp directory '%s' (does it already exist?)\n" "$tmpdir"
63+
exit 1
64+
fi
65+
66+
# Enter the temporary directory.
67+
if ! pushd "$tmpdir"; then
68+
printf "Can't enter temp directory '%s'\n" "$tmpdir"
69+
exit 1
70+
fi
71+
72+
# We can either fetch the source from the target repos by cloning them,
73+
# or simply by downloading an archive/tarball of the current 'master' branches.
74+
if [ "$fetch_source_by_cloning" = '1' ]; then
75+
# Clone folders with git.
76+
# The code above using curl and tar should work, but git diff doesn't seem to like it.
77+
{ git clone "https://github.com/${github_org1}/${github_repo1}.git" "$repo_dir1" && \
78+
git clone "https://github.com/${github_org2}/${github_repo2}.git" "$repo_dir2"; } ||
79+
{ printf "Unable to clone one or more of the target repositories.\n" && cleanup_error; }
80+
81+
# Enter each cloned repo and delete the .git folder to eliminate a bunch of garbage in the patch.
82+
remove_git "$repo_dir1"
83+
remove_git "$repo_dir2"
84+
else
85+
# Download source tarballs for both repos.
86+
repo_archive1="$repo_dir1.zip"
87+
repo_archive2="$repo_dir2.zip"
88+
{ curl -L -o "$repo_archive1" "https://github.com/${github_org1}/${github_repo1}/archive/master.zip" && \
89+
curl -L -o "$repo_archive2" "https://github.com/${github_org2}/${github_repo2}/archive/master.zip"; } || \
90+
{ printf "Couldn't download one or more of the source tarballs.\n" && cleanup_error; }
91+
92+
# Extract the contents of the source tarballs.
93+
{ mkdir "$repo_dir1" && tar -xzf "$repo_archive1" -C "$repo_dir1" && \
94+
mkdir "$repo_dir2" && tar -xzf "$repo_archive2" -C "$repo_dir2"; } || \
95+
{ printf "Couldn't extract one or more of the source tarballs.\n" && cleanup_error; }
96+
fi
97+
98+
# Remove unwanted/"don't care" files from both repos.
99+
remove_irrelevant_files "$repo_dir1"
100+
remove_irrelevant_files "$repo_dir2"
101+
102+
# Use git-diff to compare the two source trees and create a patch.
103+
# Note, the 'git diff' command reeturns with non-zero exit code if there are any warnings emitted,
104+
# which there will be -- so we can't really check the exit code to see if it succeeded'
105+
if [ "$include_all_changes" != '1' ]; then
106+
diff_filter_arg="--diff-filter=ad"
107+
fi
108+
109+
git diff --diff-algorithm=minimal "$diff_filter_arg" --no-index -- "$repo_dir1" "$repo_dir2" > "$patch_path"
110+
111+
# Cleanup the temp folder.
112+
cleanup

0 commit comments

Comments
 (0)