Как извлечь общее количество страниц фиксации для репозитория github

Я настраиваю скрипт для экспорта всех коммитов и пул-реквестов для большего списка репозиториев 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 10.04.2019 12:06

@Poshi Я совсем новичок во всем этом. Есть ли у вас какие-либо намеки на то, как перейти по «следующей» ссылке в данных обстоятельствах? Мне не нужно полное решение, просто идея о том, как это сделать. Спасибо за ваш ответ

adonis 10.04.2019 12:09

Зачем вообще использовать гитхаб? Было бы намного проще использовать git. Git сам по себе очень скриптовый.

Flimzy 10.04.2019 14:18
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
592
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вот что-то вроде того, что прокомментировал @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 ``` Когда я запускаю скрипт, он запускается, но на самом деле ничего не выводит

adonis 10.04.2019 15:28

OK - короткое отладочное обновление. Что-то не так с циклом for. Все остальное работает фантастически. Почему-то он не добавляет страницы, как должен.

adonis 10.04.2019 16:00

еще одно короткое обновление отладки: почему-то оно не принимает «истинное» значение в цикле for

adonis 10.04.2019 16:32

Привет, поэтому мое быстрое и грязное решение для этого в конце концов состояло в том, чтобы просто заменить «true» на «n <= 5000», поскольку ни в одном из репозиториев нет более 5000 * 100 = 500000 коммитов. Но все же, если у вас есть "правильное" решение для меня, я был бы очень благодарен.

adonis 10.04.2019 17:03

привет адонис. как вы указываете, for ((...;true;...)) не работает, поэтому я заменил его циклом while, который работает, а также изменил while read на while read -d' ', чтобы разбить входные данные на пробелы (или новые строки), а не только на новые строки.

webb 14.04.2019 20:14

Что ж, метод, о котором вы просите, не самый распространенный, обычно он выполняется путем выборки страниц до тех пор, пока не будут доступны данные. Но чтобы ответить на ваш конкретный вопрос, мы должны разобрать строку, содержащую информацию. Быстрый и грязный способ сделать это может быть:

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, потому что после этого мой код выглядит намного чище (кто бы мог подумать), хотя я записал все ваши заметки. Спасибо.

adonis 10.04.2019 17:04

Да, я знаю: это самый распространенный способ решения этой проблемы, потому что он проще и чище. Это то, что я сказал в своем первоначальном комментарии. В любом случае, ваш вопрос был другим: как извлечь число, которое вы искали, так что вот мой ответ :-)

Poshi 10.04.2019 17:11

может быть немного проще, хотя: grep -o '[0-9]\+; rel = "last"' <<<"$response" | grep -o '[0-9]\+'

webb 14.04.2019 20:05

или echo "$response" | perl -ne '/([0-9]+); rel = "last"/; print "$1\n";'

webb 14.04.2019 20:22

Другие вопросы по теме