Я настраиваю скрипт для экспорта всех коммитов и пул-реквестов для большего списка репозиториев github (около 4000).
После того, как основная идея скрипта работает, мне нужен способ перебрать все страницы коммитов для репозитория.
Я узнал, что могу экспортировать 100 коммитов на страницу. Для некоторых репозиториев есть еще несколько коммитов (например, 8000), так что мне нужно пройти 80 страниц.
Я не могу найти способ извлечь количество страниц из API github.
Что я сделал до сих пор, так это настроил скрипт, который перебирает все коммиты и экспортирует их в файл txt/csv.
Что мне нужно сделать, так это узнать общее количество страниц, прежде чем я начну перебирать коммиты репо.
Это здесь дает мне количество страниц таким образом, что я не могу его использовать.
curl -u "user:password" -I https://api.github.com/repos/0chain/rocksdb/commits?per_page=100
РЕЗУЛЬТАТ:
Link: https://api.github.com/repositories/152923130/commits?per_page=100&page=2; rel = "next", https://api.github.com/repositories/152923130/commits?per_page=100&page=75; rel = "last"
Мне нужно, чтобы значение 75 (или любое другое значение из других репозиториев) использовалось в качестве переменной в цикле.
Вот так:
repolist=`cat repolist.txt`
repolistarray=($(echo $repolist))
repolength=$(echo "${#repolistarray[@]}")
for (( i = 0; i <= $repolength; i++ )); do
#here i need to extract the pagenumber
pagenumber=$(curl -u "user:password" -I https://api.github.com/repos/$(echo "${repolistarray[i]}")/commits?per_page=100)
for (( n = 1; n <= $pagenumber; n++ )); do
curl -u "user:password" -s https://api.github.com/repos/$(echo "${repolistarray[i]}")/commits?per_page=100&page$(echo "$n") >committest.txt
done
done
done
Как я могу получить "75" или любой другой результат из этого
Link: https://api.github.com/repositories/152923130/commits?per_page=100&page=2; rel = "next", https://api.github.com/repositories/152923130/commits?per_page=100&page=75; rel = "last"
использовать как "n"?
@Poshi Я совсем новичок во всем этом. Есть ли у вас какие-либо намеки на то, как перейти по «следующей» ссылке в данных обстоятельствах? Мне не нужно полное решение, просто идея о том, как это сделать. Спасибо за ваш ответ
Зачем вообще использовать гитхаб? Было бы намного проще использовать git. Git сам по себе очень скриптовый.





Вот что-то вроде того, что прокомментировал @Poshi: бесконечный цикл с запросом следующей страницы, пока вы не нажмете пустую страницу, затем выйдите из внутреннего цикла, перейдя к следующему репо.
# this is the contents of a page past the last real page:
emptypage='[
]'
# here's a simpler way to iterate over each repo than using a bash array
cat repolist.txt | while read -d' ' repo; do
# loop indefinitely
page=0
while true; do
page=$((page + 1))
# minor improvement: use a variable, not a file.
# also, you don't need to echo variables, just use them
result=$(curl -u "user:password" -s \
"https://api.github.com/repos/$repo/commits?per_page=100&page=$n")
# if the result is empty, break out of the inner loop
[ "$result" = "$emptypage" ] && break
echo "$result" > committest.txt
# note that > overwrites (whereas >> appends),
# so committest.txt will be overwritten with each new page.
#
# in the final version, you probably want to process the results here,
# and then
#
# echo "$processed_results"
# done > repo1.txt
# done
#
# to ouput once per repo, or
#
# echo "$processed_results"
# done
# done > all_results.txt
#
# to output all results to a single file
done
done
Эй Уэбб, прежде всего спасибо за ваш действительно хороший комментарий. Я получил все ваши пункты, и комментарии внутри кода действительно полезны. Единственное, что он не выведет никакого файла, если я использую его так, как вы его опубликовали. У меня возникло ощущение, что с файлом TXT, который у меня есть, может быть что-то не так. Это строка, разделенная разрывами. примерно так: ``` Zolmeister/treemix Zolmeister/truffle-core Zolmeister/Tuxman Zolmeister/udio Zolmeister/UltimateICOCalendar Zolmeister/varnish-dashboard ``` Когда я запускаю скрипт, он запускается, но на самом деле ничего не выводит
OK - короткое отладочное обновление. Что-то не так с циклом for. Все остальное работает фантастически. Почему-то он не добавляет страницы, как должен.
еще одно короткое обновление отладки: почему-то оно не принимает «истинное» значение в цикле for
Привет, поэтому мое быстрое и грязное решение для этого в конце концов состояло в том, чтобы просто заменить «true» на «n <= 5000», поскольку ни в одном из репозиториев нет более 5000 * 100 = 500000 коммитов. Но все же, если у вас есть "правильное" решение для меня, я был бы очень благодарен.
привет адонис. как вы указываете, for ((...;true;...)) не работает, поэтому я заменил его циклом while, который работает, а также изменил while read на while read -d' ', чтобы разбить входные данные на пробелы (или новые строки), а не только на новые строки.
Что ж, метод, о котором вы просите, не самый распространенный, обычно он выполняется путем выборки страниц до тех пор, пока не будут доступны данные. Но чтобы ответить на ваш конкретный вопрос, мы должны разобрать строку, содержащую информацию. Быстрый и грязный способ сделать это может быть:
response = "Link: https://api.github.com/repositories/152923130/commits?per_page=100&page=2; rel=\"next\", https://api.github.com/repositories/152923130/commits?per_page=100&page=75; rel=\"last\""
<<< "$response" cut -f2- -d: | # First, get the contents of "Link": everything after the first colon
tr "," $'\n' | # Separate the different parts in different lines
grep 'rel = "last"' | # Select the line with last page information
cut -f1 -d';' | # Keep only the URL
tr "?&" $'\n' | # Split URL and its parameters, one per line
grep -e "^page" | # Select the "page" parameter
cut -f2 -d= # Finally, extract the number we are interested in
Есть и другие способы сделать это, с меньшим количеством команд, возможно, проще, но этот позволяет мне шаг за шагом объяснять. Одним из этих других способов может быть:
<<< "$response" sed 's/.*&page=\(.*\); rel = "last".*/\1/'
Это делает некоторые предположения, например, page всегда будет последним параметром.
Эй, Поши, большое спасибо. Я использовал решение Webbs, потому что после этого мой код выглядит намного чище (кто бы мог подумать), хотя я записал все ваши заметки. Спасибо.
Да, я знаю: это самый распространенный способ решения этой проблемы, потому что он проще и чище. Это то, что я сказал в своем первоначальном комментарии. В любом случае, ваш вопрос был другим: как извлечь число, которое вы искали, так что вот мой ответ :-)
может быть немного проще, хотя: grep -o '[0-9]\+; rel = "last"' <<<"$response" | grep -o '[0-9]\+'
или echo "$response" | perl -ne '/([0-9]+); rel = "last"/; print "$1\n";'
Вам не нужен этот номер. Получите первую страницу и, пока есть «следующая» ссылка, следуйте по ней, зацикливаясь до конца, где «следующая» ссылка пуста.