diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..f25a73d --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @Panquesito7 @tjgurwara99 diff --git a/.github/workflows/directory-ignore-files.yml b/.github/workflows/directory-ignore-files.yml index 58a93c7..65d7704 100644 --- a/.github/workflows/directory-ignore-files.yml +++ b/.github/workflows/directory-ignore-files.yml @@ -1,8 +1,5 @@ name: DIRECTORY.md workflow (ignore directories) -on: - push: - branches: - - 'main' +on: [workflow_dispatch] jobs: directory_builder: runs-on: ubuntu-latest @@ -15,3 +12,4 @@ jobs: working-directory: . filetypes: .cpp,.hpp ignored-directories: ./test + branch-name: directory-update-ignore diff --git a/.github/workflows/directory.yml b/.github/workflows/directory.yml index 97e2361..830cfdb 100644 --- a/.github/workflows/directory.yml +++ b/.github/workflows/directory.yml @@ -1,8 +1,5 @@ name: DIRECTORY.md workflow -on: - push: - branches: - - 'main' +on: [workflow_dispatch] jobs: directory_builder: runs-on: ubuntu-latest @@ -14,3 +11,4 @@ jobs: language: scripts working-directory: ./test filetypes: .cpp,.hpp + branch-name: directory-update diff --git a/.github/workflows/formatter-ignore-files.yml b/.github/workflows/formatter-ignore-files.yml index c6dce04..9c177a2 100644 --- a/.github/workflows/formatter-ignore-files.yml +++ b/.github/workflows/formatter-ignore-files.yml @@ -1,8 +1,5 @@ name: Test with ignore directory argument -on: - push: - branches: - - 'main' +on: [workflow_dispatch] jobs: formatter: runs-on: ubuntu-latest diff --git a/.github/workflows/formatter.yml b/.github/workflows/formatter.yml index e6fbb5c..d49c63d 100644 --- a/.github/workflows/formatter.yml +++ b/.github/workflows/formatter.yml @@ -1,8 +1,5 @@ name: Test without ignore directory argument -on: - push: - branches: - - 'main' +on: [workflow_dispatch] jobs: formatter: runs-on: ubuntu-latest diff --git a/.github/workflows/license_copyright.yml b/.github/workflows/license_copyright.yml new file mode 100644 index 0000000..17ddf26 --- /dev/null +++ b/.github/workflows/license_copyright.yml @@ -0,0 +1,11 @@ +name: License Copyright test +on: [workflow_dispatch] +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: ./license-copyright + with: + filename: LICENSE + initial_year: 2021 diff --git a/build_directory_md.py b/build_directory_md.py index cea42ff..c7e80ac 100644 --- a/build_directory_md.py +++ b/build_directory_md.py @@ -19,12 +19,8 @@ ) sys.exit() -ignore = [] -skip = [] -if len(sys.argv) == 4: - ignore = sys.argv[3].split(",") -if len(sys.argv) == 5: - skip = sys.argv[4].split(",") +ignore = sys.argv[3].split(",") if len(sys.argv) >= 4 else [] +skip = sys.argv[4].split(",") if len(sys.argv) == 5 else [] URL_BASE = f"https://github.com/TheAlgorithms/{sys.argv[0]}/blob/HEAD" @@ -33,17 +29,14 @@ def good_file_paths(top_dir: str = ".") -> Iterator[str]: for dir_path, dir_names, filenames in os.walk(top_dir): dir_names[:] = [d for d in dir_names if d != "scripts" and d[0] not in "._"] for filename in filenames: - if filename == "__init__.py": - continue - if any( + if filename == "__init__.py" or any( e.lower() in os.path.join(dir_path, filename).lower() for e in ignore ): continue if os.path.splitext(filename)[1] in sys.argv[2].split(","): path = os.path.join(dir_path, filename).lstrip(".").lstrip("/") for e in skip: - path = path.replace(e + "/", "") - path = path.replace(e + "\\", "") + path = path.replace(f"{e}/", "").replace(f"{e}\\", "") yield path diff --git a/directory_md/action.yml b/directory_md/action.yml index dd1161d..ffc5b8a 100644 --- a/directory_md/action.yml +++ b/directory_md/action.yml @@ -18,6 +18,10 @@ inputs: ignore-folders-children: description: Folders to ignore, but include children. required: false + branch-name: + description: The branch that will be used to push changes. + required: false + default: directory-update runs: using: composite steps: @@ -26,18 +30,38 @@ runs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: '3.10' # or whatever version you support + python-version: "3.x" - name: Setup Git configurations shell: bash run: | git config --global user.name github-actions[bot] - git config --global user.email 'github-actions@users.noreply.github.com' - - name: Running the formatter + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + - name: Running the directory builder + shell: bash + run: | + # If branch exists, change to that branch to prevent multiple committing/PR creation. + git checkout ${{ inputs.branch-name }} || true + + python ${{ github.action_path }}/build_directory_md.py ${{ inputs.language }} ${{ inputs.working-directory }} ${{ inputs.filetypes }} ${{ inputs.ignored-directories }} ${{ inputs.ignore-folders-children }} > DIRECTORY.md + - name: Creating a branch shell: bash run: | - python ./build_directory_md.py ${{ inputs.language }} ${{ inputs.working-directory }} ${{ inputs.filetypes }} ${{ inputs.ignored-directories }} ${{ inputs.ignore-folders-children }} > DIRECTORY.md - - name: Committing changes + git branch ${{ inputs.branch-name }} || true + git checkout ${{ inputs.branch-name }} || true + + - name: Committing, pushing, and creating a PR shell: bash run: | - git commit -m "chore: update `DIRECTORY.md`" DIRECTORY.md || true - git push origin HEAD:$GITHUB_REF || true + if [[ `git status --porcelain` ]]; + then + + git add DIRECTORY.md + + git commit -m "docs: update DIRECTORY.md" || true + git push origin ${{ inputs.branch-name }}:${{ inputs.branch-name }} --force-with-lease + + gh pr create --base ${GITHUB_REF##*/} --head ${{ inputs.branch-name }} --title 'docs: updating `DIRECTORY.md`' --body 'Updated the `DIRECTORY.md` file (see the diff. for changes).' || true + # Using `true` will make sure no errors are displayed even if there's a PR created. + fi + env: + GH_TOKEN: ${{ github.token }} diff --git a/directory_md/build_directory_md.py b/directory_md/build_directory_md.py new file mode 100644 index 0000000..cea42ff --- /dev/null +++ b/directory_md/build_directory_md.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 + +import os +import sys +from typing import Iterator + +if ".py" in sys.argv[0]: + sys.argv.pop(0) + + +if len(sys.argv) not in (3, 4, 5): + print( + "Arguments:\n" + "[0] - Language\n" + "[1] - Base path\n" + "[2] - Allowed filenames\n" + "[3] - Files or folders to ignore (optional)\n" + "[4] - Folders to ignore, but include children (optional)" + ) + sys.exit() + +ignore = [] +skip = [] +if len(sys.argv) == 4: + ignore = sys.argv[3].split(",") +if len(sys.argv) == 5: + skip = sys.argv[4].split(",") + +URL_BASE = f"https://github.com/TheAlgorithms/{sys.argv[0]}/blob/HEAD" + + +def good_file_paths(top_dir: str = ".") -> Iterator[str]: + for dir_path, dir_names, filenames in os.walk(top_dir): + dir_names[:] = [d for d in dir_names if d != "scripts" and d[0] not in "._"] + for filename in filenames: + if filename == "__init__.py": + continue + if any( + e.lower() in os.path.join(dir_path, filename).lower() for e in ignore + ): + continue + if os.path.splitext(filename)[1] in sys.argv[2].split(","): + path = os.path.join(dir_path, filename).lstrip(".").lstrip("/") + for e in skip: + path = path.replace(e + "/", "") + path = path.replace(e + "\\", "") + yield path + + +def md_prefix(i): + return f"{i * ' '}*" if i else "\n##" + + +def print_path(old_path: str, new_path: str) -> str: + old_parts = old_path.split(os.sep) + for i, new_part in enumerate(new_path.split(os.sep)): + if i + 1 > len(old_parts) or old_parts[i] != new_part: + if new_part: + print(f"{md_prefix(i)} {new_part.replace('_', ' ').title()}") + return new_path + + +def print_directory_md(top_dir: str = ".") -> None: + old_path = "" + for filepath in sorted(good_file_paths(top_dir)): + filepath, filename = os.path.split(filepath) + if filepath != old_path: + old_path = print_path(old_path, filepath) + indent = (filepath.count(os.sep) + 1) if filepath else 0 + url = "/".join((URL_BASE, filepath, filename)).replace(" ", "%20") + filename = os.path.splitext(filename.replace("_", " ").title())[0] + print(f"{md_prefix(indent)} [{filename}]({url})") + + +if __name__ == "__main__": + print_directory_md(sys.argv[1]) diff --git a/filename_formatter.sh b/filename_formatter.sh old mode 100755 new mode 100644 diff --git a/formatter/action.yml b/formatter/action.yml index cb7cbd5..7ac3e7d 100644 --- a/formatter/action.yml +++ b/formatter/action.yml @@ -1,16 +1,16 @@ name: "Filename Formatter" -description: "Format filenames into the acceptable format by TheAlgorithms opganization" +description: "Format filenames into the acceptable format by TheAlgorithms organization" author: "TheAlgorithms" inputs: filetypes: - description: Filter files by specified file types (comma separated values in a string.) Maximum two values. E.g. `.cpp,.hpp` + description: Filter files by specified file types (comma-separated values in a string.) Maximum two values. E.g. `.cpp,.hpp` required: true working-directory: description: Working/base directory of the formatter required: false default: . ignore-files: - description: Files/folders to ignored + description: Files/folders to be ignored required: false runs: using: composite @@ -21,11 +21,11 @@ runs: shell: bash run: | git config --global user.name github-actions[bot] - git config --global user.email 'github-actions@users.noreply.github.com' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' - name: Running the formatter shell: bash run: | - ./filename_formatter.sh ${{ inputs.working-directory }} ${{ inputs.filetypes }} ${{ inputs.ignore-files }} + ${{ github.action_path }}/filename_formatter.sh ${{ inputs.working-directory }} ${{ inputs.filetypes }} ${{ inputs.ignore-files }} - name: Committing changes shell: bash run: | diff --git a/formatter/filename_formatter.sh b/formatter/filename_formatter.sh new file mode 100755 index 0000000..cc9bfed --- /dev/null +++ b/formatter/filename_formatter.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +echo -e "Arguments: +[0] - Used by Bash (script filename) +[1] - Base directory +[2] - Filename type (maximum two values) +[3] - Ignored files or folders (optional; use "\""./"\"") +" + +# Separate $2 value (filename types) if it has a comma +if [[ "$2" == *","* ]]; +then + string="$2" + + str_value=${string#*,} + str_value2=${string%%,*} +else + str_value="$2" + str_value2="$2" +fi + +# Do not run script if there are no given arguments. +if [[ "$1" == "" ]] || [[ "$2" == "" ]]; +then + echo "No arguments given. Please specify minimum two arguments." + exit 1 +fi + +echo "Changed files:" + +IFS=$'\n'; set -f +for fname in $(find $1 -type f -name "*$str_value2" -or -name "*$str_value") +do + ignored_files="$(echo "$3" | tr "," "\n")" + + str="${fname}" + value=${str%/*} # If the base directory is `.`, check in all directories for the ignored filenames + + for files in $ignored_files + do + if [ "${fname}" == "$value/$files" ] || [ "$value" == "$files" ]; + then + continue 2 + fi + done + + #echo ${fname} + new_fname=$(echo "${fname}" | tr ' ' '_') + #echo " ${new_fname}" + new_fname=$(echo "${new_fname}" | tr '[:upper:]' '[:lower:]') + #echo " ${new_fname}" + new_fname=$(echo "${new_fname}" | tr '-' '_') + #echo " ${new_fname}" + if [ "${fname}" != "${new_fname}" ] + then + echo " ${fname} --> ${new_fname}" + git "mv" "${fname}" "${new_fname}" # Requires you to be in version control + fi +done +unset IFS; set +f diff --git a/license_copyright/license.yml b/license_copyright/license.yml new file mode 100644 index 0000000..1cb8289 --- /dev/null +++ b/license_copyright/license.yml @@ -0,0 +1,38 @@ +name: 'Update copyright license' +description: Updates copyright license year automatically +author: "TheAlgorithms" +inputs: + filename: + description: "License filename" + required: true + default: LICENSE +initial_year: + description: "Year of the repository's creation" + required: true + default: 2016 +runs: + using: composite + steps: + - name: Update the License + run: | + (echo "Copyright (C) ${{ inputs.initial_year }}-$(date +"%Y") TheAlgorithms and contributors"; tail -n +2 ${{ inputs.filename }}) > License.tmp + mv License.tmp ${{ inputs.filename }} + - name: Setup Git configurations + shell: bash + run: | + git config --global user.name github-actions[bot] + git config --global user.email 'github-actions@users.noreply.github.com' + - name: Commit to a new branch and push changes + shell: bash + run: | + git checkout -b license-update-${{ github.sha }} + git commit -m "docs: updating copyright license year" + git push origin license-update-${{ github.sha }}:license-update-${{ github.sha }} + - name: Creating a PR + shell: bash + run: | + if [[ $(git log --branches --not --remotes) ]]; then + gh pr create --base ${GITHUB_REF##*/} --head license-update-${{ github.sha }} --title 'docs: updating `License` copyright' --body 'Updated License copyright (see the diff. for changes).' + fi + env: + GH_TOKEN: ${{ github.token }} diff --git a/test/README.md b/test/README.md new file mode 100644 index 0000000..6d23a57 --- /dev/null +++ b/test/README.md @@ -0,0 +1,4 @@ +# Testing + +This folder is used only for testing purposes.\ +This should not be touched or modified in any way.