Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F131555519
D47416.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
D47416.diff
View Options
diff --git a/tools/tools/git/candidatematch.lua b/tools/tools/git/candidatematch.lua
deleted file mode 100755
--- a/tools/tools/git/candidatematch.lua
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/usr/libexec/flua
-
--- MFC candidate script utility - $0 from-file to-file
---
--- from-file specifies hashes that exist only in the "MFC from" branch and
--- to-file specifies the original hashes of commits already merged to the
--- "MFC to" branch.
-
--- SPDX-License-Identifier: BSD-2-Clause
--- Copyright 2024 The FreeBSD Foundation
-
--- Read a file and return its content as a table
-local function read_file(filename)
- local file = assert(io.open(filename, "r"))
- local content = {}
- for line in file:lines() do
- table.insert(content, line)
- end
- file:close()
- return content
-end
-
--- Remove hashes from 'set1' list that are present in 'set2' list
-local function set_difference(set1, set2)
- local set2_values = {}
- for _, value in ipairs(set2) do
- set2_values[value] = true
- end
-
- local result = {}
- for _, value in ipairs(set1) do
- if not set2_values[value] then
- table.insert(result, value)
- end
- end
- return result
-end
-
--- Execute a command and print to stdout
-local function exec_command(command)
- local handle = io.popen(command)
- local output = handle:read("a")
- handle:close()
- io.write(output)
-end
-
--- Main function
-local function main()
- local from_file = arg[1]
- local to_file = arg[2]
- local exclude_file = arg[3]
-
- if not from_file or not to_file then
- print("Usage: flua $0 from-file to-file")
- return
- end
-
- local from_hashes = read_file(from_file)
- local to_hashes = read_file(to_file)
-
- local result_hashes = set_difference(from_hashes, to_hashes)
-
- if exclude_file then
- exclude_hashes = read_file(exclude_file)
- result_hashes = set_difference(result_hashes, exclude_hashes)
- end
-
- -- Print the result
- for _, hash in ipairs(result_hashes) do
- exec_command("git show --pretty='%h %s' --no-patch " .. hash)
- end
-end
-
-main()
diff --git a/tools/tools/git/mfc-candidates.lua b/tools/tools/git/mfc-candidates.lua
new file mode 100755
--- /dev/null
+++ b/tools/tools/git/mfc-candidates.lua
@@ -0,0 +1,218 @@
+#!/usr/libexec/flua
+
+-- SPDX-License-Identifier: BSD-2-Clause
+-- Copyright 2024 The FreeBSD Foundation
+
+-- MFC candidate search utility. Identify hashes that exist only in the
+-- "MFC from" branch and do not have a corresponding "cherry picked from"
+-- commit in the "MFC to" branch.
+
+-- Execute a command and return its output. A final newline is stripped,
+-- similar to sh.
+local function exec_command(command)
+ local handle = assert(io.popen(command))
+ local output = handle:read("a")
+ handle:close()
+ if output:sub(-1) == "\n" then
+ return output:sub(1, -2)
+ end
+ return output
+end
+
+-- Return a table of cherry-pick (MFC) candidates.
+local function read_from(from_branch, to_branch, author, dirspec)
+ local command = "git rev-list --first-parent --reverse "
+ command = command .. to_branch .. ".." .. from_branch
+ if #author > 0 then
+ command = command .. " --committer \\<" .. author .. "@"
+ end
+ if dirspec then
+ command = command .. " " .. dirspec
+ end
+ if verbose > 1 then
+ print("Obtaining MFC-from commits using command:")
+ print(command)
+ end
+ local handle = assert(io.popen(command))
+ local content = {}
+ for line in handle:lines() do
+ table.insert(content, line)
+ end
+ handle:close()
+ return content
+end
+
+-- Return a table of original hashes of changes that have already been
+-- cherry-picked (MFC'd).
+local function read_to(from_branch, to_branch, dirspec)
+ local command = "git log " .. from_branch .. ".." .. to_branch
+ command = command .. " --grep 'cherry picked from'"
+ if dirspec then
+ command = command .. " " .. dirspec
+ end
+ if verbose > 1 then
+ print("Obtaining MFC-to commits using command:")
+ print(command)
+ end
+ local handle = assert(io.popen(command))
+ local content = {}
+ for line in handle:lines() do
+ local hash = line:match("%(cherry picked from commit ([0-9a-f]+)%)")
+ if hash then
+ table.insert(content, hash)
+ end
+ end
+ handle:close()
+ return content
+end
+
+-- Read a commit exclude file and return its content as a table. Comments
+-- starting with # and text after a hash is ignored.
+local function read_exclude(filename)
+ local file = assert(io.open(filename, "r"))
+ local content = {}
+ for line in file:lines() do
+ local hash = line:match("^%x+")
+ if hash then
+ -- Hashes are 40 chars; if less, expand short hash.
+ if #hash < 40 then
+ hash = exec_command(
+ "git show --pretty=%H --no-patch " .. hash)
+ end
+ table.insert(content, hash)
+ end
+ end
+ file:close()
+ return content
+end
+
+--- Remove hashes from 'set1' list that are present in 'set2' list
+local function set_difference(set1, set2)
+ local set2_values = {}
+ for _, value in ipairs(set2) do
+ set2_values[value] = true
+ end
+
+ local result = {}
+ for _, value in ipairs(set1) do
+ if not set2_values[value] then
+ table.insert(result, value)
+ end
+ end
+ return result
+end
+
+-- Global state
+verbose = 0
+
+local function params(from_branch, to_branch, author)
+ print("from: " .. from_branch)
+ print("to: " .. to_branch)
+ if #author > 0 then
+ print("author/committer: " .. author)
+ else
+ print("author/committer: <all>")
+ end
+end
+
+local function usage(from_branch, to_branch, author)
+ local script_name = arg[0]:match("([^/]+)$")
+ print(script_name .. " [-ah] [-f from_branch] [-t to_branch] [-u user] [-X exclude_file] [path ...]")
+ print()
+ params(from_branch, to_branch, author)
+end
+
+-- Main function
+local function main()
+ local from_branch = "freebsd/main"
+ local to_branch = ""
+ local author = os.getenv("USER") or ""
+ local dirspec = nil
+
+ local url = exec_command("git remote get-url freebsd")
+ local freebsd_repo = string.match(url, "[^/]+$")
+ freebsd_repo = string.gsub(freebsd_repo, ".git$", "")
+ if freebsd_repo == "ports" or freebsd_repo == "freebsd-ports" then
+ local year = os.date("%Y")
+ local month = os.date("%m")
+ local qtr = math.ceil(month / 3)
+ to_branch = "freebsd/" .. year .. "Q" .. qtr
+ elseif freebsd_repo == "src" or freebsd_repo == "freebsd-src" then
+ to_branch = "freebsd/stable/14"
+ -- If pwd is a stable or release branch tree, default to it.
+ local cur_branch = exec_command("git symbolic-ref --short HEAD")
+ if string.match(cur_branch, "^stable/") then
+ to_branch = cur_branch
+ elseif string.match(cur_branch, "^releng/") then
+ to_branch = cur_branch
+ local major = string.match(cur_branch, "%d+")
+ from_branch = "freebsd/stable/" .. major
+ end
+ else
+ print("pwd is not under a ports or src repository.")
+ return
+ end
+
+ local do_help = false
+ local exclude_file = nil
+ local i = 1
+ while i <= #arg and arg[i] do
+ local opt = arg[i]
+ if opt == "-a" then
+ author = ""
+ elseif opt == "-f" then
+ from_branch = arg[i + 1]
+ i = i + 1
+ elseif opt == "-h" then
+ do_help = true
+ i = i + 1
+ elseif opt == "-t" then
+ to_branch = arg[i + 1]
+ i = i + 1
+ elseif opt == "-u" then
+ author = arg[i + 1]
+ i = i + 1
+ elseif opt == "-v" then
+ verbose = verbose + 1
+ elseif opt == "-X" then
+ exclude_file = arg[i + 1]
+ print ("-X not working")
+ i = i + 1
+ else
+ break
+ end
+ i = i + 1
+ end
+
+ if do_help then
+ usage(from_branch, to_branch, author)
+ return
+ end
+
+ if arg[i] then
+ dirspec = arg[i]
+ --print("dirspec = " .. dirspec)
+ -- XXX handle multiple dirspecs?
+ end
+
+ if verbose > 0 then
+ params(from_branch, to_branch, author)
+ end
+
+ local from_hashes = read_from(from_branch, to_branch, author, dirspec)
+ local to_hashes = read_to(from_branch, to_branch, dirspec)
+
+ local result_hashes = set_difference(from_hashes, to_hashes)
+
+ if exclude_file then
+ exclude_hashes = read_exclude(exclude_file)
+ result_hashes = set_difference(result_hashes, exclude_hashes)
+ end
+
+ -- Print the result
+ for _, hash in ipairs(result_hashes) do
+ print(exec_command("git show --pretty='%h %s' --no-patch " .. hash))
+ end
+end
+
+main()
diff --git a/tools/tools/git/mfc-candidates.sh b/tools/tools/git/mfc-candidates.sh
--- a/tools/tools/git/mfc-candidates.sh
+++ b/tools/tools/git/mfc-candidates.sh
@@ -29,139 +29,5 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
-from_branch=freebsd/main
-author="${USER}"
-
-# Get the FreeBSD repository
-repo=$(basename "$(git remote get-url freebsd 2>/dev/null)" .git 2>/dev/null)
-
-if [ "${repo}" = "ports" -o "${repo}" = "freebsd-ports" ]; then
- year=$(date '+%Y')
- month=$(date '+%m')
- qtr=$(((month-1) / 3 + 1))
- to_branch="freebsd/${year}Q${qtr}"
-elif [ "${repo}" = "src" -o "${repo}" = "freebsd-src" ]; then
- to_branch=freebsd/stable/14
- # If pwd is a stable or release branch tree, default to it.
- cur_branch=$(git symbolic-ref --short HEAD 2>/dev/null)
- case $cur_branch in
- stable/*)
- to_branch=$cur_branch
- ;;
- releng/*)
- to_branch=$cur_branch
- major=${cur_branch#releng/}
- major=${major%.*}
- from_branch=freebsd/stable/$major
- esac
-else
- echo "pwd is not under a ports or src repository."
- exit 0
-fi
-
-params()
-{
- echo "from: $from_branch"
- echo "to: $to_branch"
- if [ -n "$author" ]; then
- echo "author/committer: $author"
- else
- echo "author/committer: <all>"
- fi
-}
-
-usage()
-{
- echo "usage: $(basename $0) [-ah] [-f from_branch] [-t to_branch] [-u user] [-X exclude_file] [path ...]"
- echo
- params
- exit 0
-}
-
-while getopts "af:ht:u:vX:" opt; do
- case $opt in
- a)
- # All authors/committers
- author=
- ;;
- f)
- from_branch=$OPTARG
- ;;
- h)
- usage
- ;;
- t)
- to_branch=$OPTARG
- ;;
- u)
- author=$OPTARG
- ;;
- v)
- verbose=1
- ;;
- X)
- if [ ! -r "$OPTARG" ]; then
- echo "Exclude file $OPTARG not readable" >&2
- exit 1
- fi
- exclude_file=$OPTARG
- ;;
- esac
-done
-shift $(($OPTIND - 1))
-
-if [ $verbose ]; then
- params
- echo
-fi
-
-authorarg=
-if [ -n "$author" ]; then
- # Match user ID in the email portion of author or committer
- authorarg="--committer <${author}@"
-fi
-
-# Commits in from_branch after branch point
-commits_from()
-{
- git rev-list --first-parent --reverse $authorarg $to_branch..$from_branch "$@"
-}
-
-# "cherry picked from" hashes from commits in to_branch after branch point
-commits_to()
-{
- git log $from_branch..$to_branch --grep 'cherry picked from' "$@" |\
- sed -E -n 's/^[[:space:]]*\(cherry picked from commit ([0-9a-f]+)\)[[:space:]]*$/\1/p'
-}
-
-# Turn a list of short hashes (and optional descriptions) into a list of full
-# hashes.
-canonicalize_hashes()
-{
- while read hash rest; do
- case "${hash}" in
- "#"*) continue ;;
- esac
- if ! git show --pretty=%H --no-patch $hash; then
- echo "error parsing hash list" >&2
- exit 1
- fi
- done | sort
-}
-
-workdir=$(mktemp -d /tmp/find-mfc.XXXXXXXXXX)
-from_list=$workdir/commits-from
-to_list=$workdir/commits-to
-
-if [ -n "$exclude_file" ]; then
- exclude_list=$workdir/commits-exclude
- canonicalize_hashes < $exclude_file > $exclude_list
-fi
-
-commits_from "$@" > $from_list
-commits_to "$@" > $to_list
-
-/usr/libexec/flua $(dirname $0)/candidatematch.lua \
- $from_list $to_list $exclude_list
-
-rm -rf "$workdir"
+# Backwards compatibility wrapper
+/usr/libexec/flua $(dirname $0)/mfc-candidates.lua "$@"
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Oct 10, 5:39 AM (20 h, 18 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
23520426
Default Alt Text
D47416.diff (11 KB)
Attached To
Mode
D47416: [draft] mfc-candidates: convert to Lua
Attached
Detach File
Event Timeline
Log In to Comment