从GitHub存储库克隆/下载特定文件

GitHub 上有一个名为platform_frameworks_base的 Git 存储库,其中包含部分 Android 源代码。
我编写了一个应用程序,该应用程序会回复该项目中的所有 .aidl 文件,因此它会在第一次启动时下载所有文件。
到目前为止,我通过从项目根目录下载文件Android.bp,从该文件中提取所有以 .aidl 结尾的文件路径,然后明确地将它们一一下载。

例如,如果我找到了这个文件路径:

media/java/android/media/IAudioService.aidl

我知道我可以像这样下载它:

wget https://raw.githubusercontent.com/aosp-mirror/platform_frameworks_base/android-10.0.0_r47/media/java/android/media/IAudioService.aidl

在 Android 10 (git tag: android-10.0.0_r47)之前,这可以正常工作。
从 Android 11(例如 git tag: android-11.0.0_r33)开始,文件路径使用通配符而不是完整路径。看到这个Android.bp。

它现在只包含通配符/glob 文件路径,如:

media/java/**/*.aidl
location/java/**/*.aidl

等等...

我目前的“解决方案”:

  1. 克隆 repo(仅我们关心的分支的最后一次提交):

    git clone --depth=1 -b android-11.0.0_r33 https://github.com/aosp-mirror/platform_frameworks_base.git

  2. 从 Android.bp 中提取通配符/glob 路径。

    cat Android.bp | grep '.aidl"' | cut -d'"' -f2

  3. 查找与通配符/glob 路径匹配的所有文件。

    例如 shopt -s globstar && echo media/java/**/*.aidl

但是下载过程需要很长时间,因为存储库包含超过 1 GB的二进制文件。即使我只是克隆我关心的分支的最后一次提交。

现在我的实际问题是:
我怎样才能下载.aidl我真正关心的文件?(理想情况下不解析 GitHub 中每个文件夹的 HTML。)
或者
如何在没有所有二进制文件的情况下下载/克隆存储库?(可能用 git 不可能?)

编辑:

我尝试使用 GitHub API 递归遍历所有目录,但我立即收到 API rate limit exceeded 错误:

g_aidlFiles=""

# Recursively go through all directories and the paths to all found .aidl files in the global g_aidlFile variable
GetAidlFilesFromGithub() {
    l_dirUrl="${1-}"
    if [ "$l_dirUrl" == "" ]; then
        echo "ERROR: Directory URL not provided in GetAidlFilesFromGithub"
        exit 1
    fi
    
    echo "l_dirUrl: ${l_dirUrl}"
    
    l_rawRes="$(curl -s -i $l_dirUrl)"
    l_statusCode="$(echo "$l_rawRes" | grep HTTP | head -1 | cut -d' ' -f2)"
    l_resBody="$(echo "$l_rawRes" | sed '1,/^s*$/d')"
    if [[ $l_statusCode == 4* ]] || [[ $l_statusCode == 5* ]]; then
        echo "ERROR: Request failed!"
        echo "Response status: $l_statusCode"
        echo "Reponse body:"
        echo "$l_resBody"
        exit 1
    fi
    
    l_currentDirJson="$(echo "$l_resBody")"
    if [ "$l_currentDirJson" == "" ]; then
        echo "ERROR: l_currentDirJson is empty"
        exit 1
    fi
    
    l_newAidlFiles="$(echo "$l_currentDirJson" | jq '.[] | select(.type=="file") | select(.path | endswith(".aidl")) | .path')"
    
    if [ "$l_newAidlFiles" != "" ]; then
        echo "l_newAidlFiles: ${l_newAidlFiles}"
        g_aidlFiles="${g_aidlFiles}n${l_newAidlFiles}"
    fi

    l_subDirUrls="$(echo "$l_currentDirJson" | jq '.[] | select(.type=="dir") | .url')"
    if [ "$l_subDirUrls" != "" ]; then
        echo "$l_subDirUrls" | while IFS= read -r l_subDirUrl ; do 
            (GetAidlFilesFromGithub "$l_subDirUrl")
        done
    else
        echo "No subdirs found."
    fi
}

GetAidlFilesFromGithub "https://api.github.com/repos/aosp-mirror/platform_frameworks_base/contents?ref=android-11.0.0_r33"

据我所知,我的所有用户都必须创建一个 GitHub 帐户并创建一个 OAUTH 秘密来提高限制。这绝对不是我的选择。我希望我的应用程序易于使用。

回答

Since the repo's on GitHub, which supports filters, easiest is probably to use its filter support.

git clone --no-checkout --depth=1 --filter=blob:none 
        https://github.com/aosp-mirror/platform_frameworks_base
cd platform_frameworks_base
git reset -q -- *.aidl
git checkout-index -a

which could probably be finessed quite a bit to get the files sent in a single pack instead of the one-at-a-time-fetch that produces.

For instance, instead of blob:none say blob:limit=16384, that gets most of them up front.

To do this in your own code, without relying on a Git install, you'd need to implement the git protocol. Here's the online intro with pointers to the actual Git docs. It's not hard, you send text lines back and forth until the server spits the gobsmacking lot of data you wanted, then you pick through it. You don't need to use https, github supports the plain git protocol. Try running that clone command with GIT_TRACE=1 GIT_PACKET_TRACE=1.

  • Fixed in 2.27.0, specifically 167a575

以上是从GitHub存储库克隆/下载特定文件的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>