diff --git a/.github/workflows/count.yml b/.github/workflows/count.yml new file mode 100644 index 000000000..b3fb95566 --- /dev/null +++ b/.github/workflows/count.yml @@ -0,0 +1,55 @@ +name: Check Line Counts +on: [push] + +jobs: + sz: + name: Core MFC Line Difference + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - name: Checkout code from PR branch + uses: actions/checkout@v4 + with: + path: pr + + - name: Checkout code from MFC master + uses: actions/checkout@v4 + with: + repository: ${{ github.event.pull_request.repository }} + ref: ${{ github.event.pull_request.base.ref }} + path: base + # repository: MFlowCode/MFC + # ref: master + # path: base + + - name: Setup MFCs + run: | + BASE="$GITHUB_WORKSPACE/base" + PR="$GITHUB_WORKSPACE/pr" + cd $BASE + ./mfc.sh count + cd $PR + ./mfc.sh count + + - name: Counting Lines + run: | + BASE="$GITHUB_WORKSPACE/base" + PR="$GITHUB_WORKSPACE/pr" + cd $BASE + echo "___BASE______________" + ./mfc.sh count + cd $PR + echo "___PR________________" + ./mfc.sh count + + # - name: Get Line Diff + # run: | + # BASE="$GITHUB_WORKSPACE/base" + # PR="$GITHUB_WORKSPACE/pr" + # cd $BASE + # export MFC_PR=$PR + # pwd + # ./mfc.sh count_diff + diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 4e3431ab2..da5b2afcf 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -27,4 +27,3 @@ jobs: file: toolchain/Dockerfile push: true tags: ${{ secrets.DOCKER_USERNAME }}/mfc:latest - diff --git a/.github/workflows/spelling.yml b/.github/workflows/spelling.yml index 6e712e638..a170f4e52 100644 --- a/.github/workflows/spelling.yml +++ b/.github/workflows/spelling.yml @@ -12,4 +12,4 @@ jobs: uses: actions/checkout@v3 - name: Spell Check - uses: crate-ci/typos@master \ No newline at end of file + uses: crate-ci/typos@master diff --git a/toolchain/main.py b/toolchain/main.py index d9bdfb9fc..6c42fd68b 100644 --- a/toolchain/main.py +++ b/toolchain/main.py @@ -49,7 +49,7 @@ def __checks(): def __run(): {"test": test.test, "run": run.run, "build": build.build, "clean": build.clean, "bench": bench.bench, "count": count.count, - "packer": packer.packer + "packer": packer.packer, "count_diff": count.count_diff }[ARG("command")]() diff --git a/toolchain/mfc/args.py b/toolchain/mfc/args.py index 0eb1db3ee..5ac583b6f 100644 --- a/toolchain/mfc/args.py +++ b/toolchain/mfc/args.py @@ -24,6 +24,7 @@ def parse(config): clean = parsers.add_parser(name="clean", help="Clean build artifacts.", formatter_class=argparse.ArgumentDefaultsHelpFormatter) bench = parsers.add_parser(name="bench", help="Benchmark MFC (for CI).", formatter_class=argparse.ArgumentDefaultsHelpFormatter) count = parsers.add_parser(name="count", help="Count LOC in MFC.", formatter_class=argparse.ArgumentDefaultsHelpFormatter) + count_diff = parsers.add_parser(name="count_diff", help="Count LOC in MFC.", formatter_class=argparse.ArgumentDefaultsHelpFormatter) packer = parsers.add_parser(name="packer", help="Packer utility (pack/unpack/compare)", formatter_class=argparse.ArgumentDefaultsHelpFormatter) packers = packer.add_subparsers(dest="packer") @@ -126,12 +127,16 @@ def add_common_arguments(p, mask = None): # === COUNT === add_common_arguments(count, "g") + # === COUNT === + add_common_arguments(count_diff, "g") + args: dict = vars(parser.parse_args()) args["--"] = args.get("--", []) # Add default arguments of other subparsers for name, parser in [("run", run), ("test", test), ("build", build), - ("clean", clean), ("bench", bench), ("count", count)]: + ("clean", clean), ("bench", bench), ("count", count), + ("count_diff", count_diff)]: if args["command"] == name: continue diff --git a/toolchain/mfc/count.py b/toolchain/mfc/count.py index b21962e65..bdff3038c 100644 --- a/toolchain/mfc/count.py +++ b/toolchain/mfc/count.py @@ -2,7 +2,7 @@ import rich.table from .state import ARG -from .common import MFC_ROOTDIR, format_list_to_string +from .common import MFC_ROOTDIR, format_list_to_string, MFCException from .printer import cons def handle_dir(dirpath: str) -> typing.Tuple[typing.List[typing.Tuple[str, int]], int]: @@ -11,9 +11,18 @@ def handle_dir(dirpath: str) -> typing.Tuple[typing.List[typing.Tuple[str, int]] for filepath in glob.glob(os.path.join(dirpath, '*.*f*')): with open(filepath) as f: - n = sum(1 if not l.isspace() else 0 for l in f.read().split('\n')) - files.append((filepath, count)) - total += n + counter = 0 + for l in f.read().split('\n'): + # Skip whitespace + if l.isspace() or len(l) == 0: + continue + # Skip comments but not !$acc ones! + if l.lstrip().startswith("!") and not l.lstrip().startswith("!$acc"): + continue + counter += 1 + + files.append((filepath, counter)) + total += counter files.sort(key=lambda x: x[1], reverse=True) @@ -42,3 +51,54 @@ def count(): cons.print(f"[bold]Total {target_str_list} lines: [bold cyan]{total}[/bold cyan].[/bold]") cons.print() cons.unindent() + +# pylint: disable=too-many-locals +def count_diff(): + target_str_list = format_list_to_string(ARG('targets'), 'magenta') + cons.print(f"[bold]Counting lines of code in {target_str_list}[/bold] (excluding whitespace lines)") + cons.indent() + + total = 0 + MFC_COMPAREDIR=os.getenv('MFC_PR') + if MFC_COMPAREDIR is None: + raise MFCException("MFC_PR is not in your environment.") + + print('compare dir', MFC_COMPAREDIR) + + # MFC_COMPAREDIR="/Users/spencer/Downloads/MFC-shbfork" + for codedir in ['common'] + ARG("targets"): + dirfiles_root, dircount = handle_dir(os.path.join(MFC_ROOTDIR, 'src', codedir)) + dirfiles_pr, dircount_pr = handle_dir(os.path.join(MFC_COMPAREDIR, 'src', codedir)) + table = rich.table.Table(show_header=True, box=rich.table.box.SIMPLE) + table.add_column(f"File (in [magenta]{codedir}[/magenta])", justify="left") + table.add_column(f"Lines [HEAD] ([cyan]{dircount}[/cyan])", justify="right") + table.add_column(f"Lines [PR] ([cyan]{dircount_pr}[/cyan])", justify="right") + table.add_column("", justify="right") + table.add_column("Diff", justify="right") + + ii = 0 + files_pr = [os.path.basename(dirfiles_pr[i][0]) for i in range(len(dirfiles_pr))] + files_root = [os.path.basename(dirfiles_root[i][0]) for i in range(len(dirfiles_root))] + + PLUS = "++ " + MINUS = "-- " + + for filepath, n in dirfiles_pr: + for filepath_root, _ in dirfiles_root: + if os.path.basename(dirfiles_pr[ii][0]) == os.path.basename(filepath_root): + diff_count = n - dirfiles_root[ii][1] + mycolor = "red" if diff_count > 0 else "green" + mysymbol = PLUS if diff_count > 0 else MINUS + table.add_row(f"{os.path.basename(filepath)}", f"[bold cyan]{n}[/bold cyan]", f"[bold cyan]{dirfiles_root[ii][1]}[/bold cyan]", mysymbol, f"[bold {mycolor}]{diff_count}[/bold {mycolor}]") + + if files_pr[ii] not in files_root: + table.add_row(f"{os.path.basename(files_pr[ii])}", "----", f"[bold green]{n}[/bold green]", PLUS, f"[bold green]{n}[/bold green]") + ii += 1 + + total += dircount + + cons.raw.print(table) + + cons.print(f"[bold]Total {target_str_list} lines: [bold cyan]{total}[/bold cyan].[/bold]") + cons.print() + cons.unindent()