터미널에서 파일 경로를 수정하는 풀 요청 찾기

15352 단어 githubbashgit
작업 중인 동일한 파일을 다른 사람들이 어떻게 변경하고 있는지 궁금한 적이 있습니까? 특정 코드 조각이 미래에 어떤 모습일지에 대한 통찰력을 제공할 수 있습니다. 확실히 OSS 초보자가 다른 사람들이 특정 기능을 구축하는 방법을 식별하는 데 도움이 될 수 있습니다.

자, 오늘의 포스팅은 바로 그것을 해결하는 것입니다. 간단한 쉘 스크립트를 직접 만들어 볼까요?

전제 조건



작업을 시작하기 전에 다음 CLI 도구가 설치되어 있는지 확인하십시오.
  • gh - Github’s CLI tool
  • fzf - A command-line fuzzy finder
  • jq - Command-line JSON processor

  • Once you install gh, make sure to authenticate yourself using gh auth login



    풀 리퀘스트 내놔



    첫 번째 작업은 사용자에게 찾을 로컬 파일 경로를 선택하도록 요청하는 것입니다. 이는 구문 분석git ls-files을 통해 수행할 수 있으며 더 나은 상호 작용을 위해 fzf도 사용할 것입니다.

    git_file=$(git ls-files | fzf \
      --prompt="Choose File: " \
      --height 40% --reverse \
      --header="Choose a file to find pull requests on github that modify it"
    )
    
    


    해결되면 열려 있는 풀 요청을 모두 찾아야 합니다. 이 작업은 gh pr list에서 수행합니다.

    fetch_prs() {
      pr_fetch_limit=100
      printf "%s\n\n" "Hold tight while we look for PRs ✋👀 that modify $git_file"
      all_open_prs=$(gh pr list --limit $pr_fetch_limit --json number,title,url,files,author,baseRefName,headRefName)
      total_prs=$(jq length <<< "$all_open_prs")
    }
    
    


    기본적으로 gh는 30개의 공개 풀 요청만 로드합니다. 지금은 이 제한을 100으로 늘렸으며 나중에 사용자에게 이 값에 대한 제어 권한을 부여하여 이 문제를 해결할 것입니다.

    위의 코드를 실행하면 다음과 유사한 출력이 표시됩니다.

    [
        {
          "author": {
            "login": "authorUsername"
          },
          "baseRefName": "somebranch",
          "files": [
            {
              "path": ".gitmodules",
              "additions": 2,
              "deletions": 2
            },
            ...
          ],
          "headRefName": "dev",
          "number": 300,
          "title": "my new feature",
          "url": "https://github.com/user/repo/pull/300"
        },
        ...
    ]
    
    

    files 배열 내부의 PR에서 변경된 모든 파일을 얻습니다. 이 JSON 배열의 모든 요소를 ​​간단히 반복하여 git_file를 필터링할 수 있습니다.

    find_files_prs(){
      for (( pri=0; pri<total_prs; pri++ )); do
          readarray -t changed_files < <(echo "$all_open_prs" | jq .["$pri"].files[].path)
    
          if [["${changed_files[*]}" =~ ${git_file} ]]; then
              pr_branch=$(jq -r .["$pri"].headRefName <<< "$all_open_prs")
              base_branch=$(jq -r .["$pri"].baseRefName <<< "$all_open_prs")
    
              printf "%s " "$(jq -r .["$pri"].title <<< "$all_open_prs") ($pr_branch$base_branch)"
              printf "%s\n" "by $(jq -r .["$pri"].author.login <<< "$all_open_prs")"
              printf "%s\n\n" "PR Link: $(jq -r .["$pri"].url <<< "$all_open_prs")"
    
              prs_count=$((prs_count+1))
          fi
      done
    
      if [[$prs_count == 0]]; then
        printf "%s\n" "Oops!, No pull requests found that modify this file path"
      else
        printf "%s\n" "Found $prs_count open pull requests that modify $git_file"
      fi
    }
    
    


    이 코드 조각에서 많은 일이 진행되고 있습니다.
  • 변경된 파일 경로의 JSON 배열을 bash 배열로 변환합니다changed_files.
  • 각 경로를 반복하여 사용자가 제공한 경로와 일치하는지 확인합니다.
  • 또한 PR 링크, 기본 및 대상 분기, 작성자 사용자 이름과 같이 필요한 모든 정보를 출력합니다.

  • 잠깐만 뭔가 빠진거 맞죠 🤔? diff는 어떻습니까? gh pr list 명령은 diff 데이터를 제공하지 않지만 다른 명령gh pr diff을 사용하여 특정 PR에 대한 diff를 얻을 수 있습니다.

    show_diff=0
    
    get_diff() {
      if [[$show_diff = 1]];then
        printf "%s\n" "Getting diff for PR #$2"
        # filepath with escaped slashes
        clean_filepath=${1//\//\\/}
        gh pr diff --color always "$2" | sed -n "/diff --git a\/$clean_filepath/d;/diff/q;p"
        printf "\n"
      fi
    }
    
    

    show_diff는 스크립트 인수를 통해 제어할 전역 플래그가 될 것입니다. 나중에 더 자세히 설명하자면 사용자가 제공한 파일 경로 1개에 대해서만 diff를 표시해야 합니다. 이를 위해 sed를 사용하여 패턴1,/diff --git a/<filepath>과 다음 파일 변경에 대한 diff를 표시하는 패턴diff 사이의 모든 것을 가져왔습니다.

    모든 것을 하나로 모아야 할 때입니다. 스크립트를 올바르게 실행하기 위해 몇 가지 드라이버 코드를 추가해 보겠습니다.

    while getopts "dl:" o; do
        case "${o}" in
            d)
                d=${OPTARG}
                if [["$d" == ""]]; then
                  show_diff=1
                fi
                ;;
            l)
                l=${OPTARG}
                ;;
            *)
                printf "%s\n" "You seem to be lost" && exit
                ;;
        esac
    done
    
    if [[$l != ""]];then
      pr_fetch_limit=$l
      printf "%s\n" "Using $pr_fetch_limit as PR fetch limit."
    else
      printf "%s\n" "Using $pr_fetch_limit as default PR fetch limit. Pass the -l flag to modify it"
    fi
    
    fetch_prs
    find_files_prs
    
    


    데모 및 소스



    무엇이든 참조하거나 해킹하려는 경우 소스는 available here입니다. 나는 스크립트의 출력을 아름답게 꾸미기 위해 자유를 얻었습니다. 최종 버전은 다음과 같습니다.



    할 일 및 테이크 아웃



    이 스크립트를 다음 단계로 끌어 올릴 수 있는 많은 것들이 있습니다.
  • GitHub의 API에 의해 제한되지만 PR 내에서 파일 변경에 대한 퍼머링크를 제공해야 합니다.
  • gh pr list --state all를 사용하거나 사용자에게 원하는 것을 묻는 더 나은 방법을 사용하여 폐쇄/병합된 PR 가져오기를 지원합니다.
  • 단일 파일 경로에 대해 diff를 구문 분석할 수 있었지만, 매우 불쾌하고 오류가 발생하기 쉬운 방법이라고 생각하며 이상적으로는 이 기능이 gh 내에 있어야 합니다. 이것을 추적하기 위해 issue을 생성했습니다. 어디로 가는지 봅시다.
  • 좋은 웹페이지 즐겨찾기