ChooChooLoco

ChooChooLoco

Дятл dimio.org Техноблевничок: https://t.me/+kSNYhy8GR5VhMDFi
На Пикабу
2392 рейтинг 15 подписчиков 19 подписок 68 постов 7 в горячем
Награды:
Пикабу 16 лет! За киноманство За киберзащиту За участие в Пикабу-Оскаре
64

Git: извлечение первого и последнего комита по автору

В силу определённых обстоятельств – периодически стал возникать вопрос, в каких временных рамках я занимался тем или иным проектом. И готового ответа на него у меня не было – как-то не приходило в голову фиксировать подобную информацию.

Но есть же git – ведь он поможет? Ведь поможет, да?

Git поможет!

Возникла тривиальная идея – вытащить эту информацию из гит-лога. Первый и последний коммиты – плюс-минус дадут требуемые рамки. Достаточно найти все коммиты определённого автора (в данном случае – себя) и взять первый+последний.

Git alias для поиска по автору

Чтобы не запоминать (или не искать в истории) довольно длинную команду – её удобно запихать в пользовательский alias (именно гита, не оболочки). Например – в ~/.gitconfig прописать (в секции [alias]):

В частном случае – это уже работает достаточно удобно и выглядит примерно так:

user@host:~/single-repo$ git first-last-by-author dmitry f887e8aa55 Dmitry 2022-06-26

6f7a97ded7 Dmitry 2021-04-08

Когда репозиторий для поиска – один. Или парочка. Или… Нет, когда их парочка сотен – становится грустно. Идея явно требует развития!

One Function to find them all

Для решения задачи поиска по набору репозиториев – пришлось воспользоваться функциями оболочки. Они у меня сложены в отдельном файле ~/.config/bash/bash_functions.

На базе команды для обновления репозиториев и приведённого выше гит-алиаса для поиска по автору – сделал такую вот bash-функцию:

Теперь поиск работает и в общем случае (в каталоге multi-repo лежит куча git-репозиториев):

user@host:~/multi-repo$ git-first-last-commit-by-author dmitry

8f1d4ae Dmitry 2022-08-16

83a8f89c Dmitry 2023-02-15

Видно, что здесь порядок сортировки по датам – прямой. Мне так удобней, но всегда можно использовать ключ --reverse для sort внутри git-first-last-commit-by-author().

Показать полностью 2
1

LeetCode 125. Valid Palindrome

Очередная задачка уровня Easy, но с довольно низким показателем Acceptance (44.4%). Что выражается в достаточно обширном наборе граничных случаев, некоторые из которых делают больно 🙂

Было желание сделать за один проход по исходной строке (без выделения дополнительно памяти). Вроде даже получилось, если ориентироваться на статистику запуска с LeetCode.

Надоело бороться с "Цитатой" в бесплодных попытках использовать её для оформления кода, которое можно был бы читать без самовоспламенения пердячей тяги. Поэтому тут будет пикча, в нормальном виде - в оригинале.

LeetCode 125. Valid Palindrome

Success: Runtime:2 ms, faster than 99.92% of Java online submissions. Memory Usage:42.3 MB, less than 87.41% of Java online submissions.

Показать полностью 1
1

LeetCode 1935. Maximum Number of Words You Can Type

Тоже забавная задачка – со “сломанной клавиатурой”. Решил в ней Arrays.binarySearch использовать для поиска буквы слова в наборе “сломанных клавишей”, да и чтобы не забыть о его (метода) существовании в целом.

Судя по статистике – нормально получилось, в общем-то.

class Solution {

public int canBeTypedWords(String text, String brokenLetters) {

var brL = brokenLetters.toCharArray();

Arrays.sort(brL);

var words = text.split(" ");

int canTypeCnt = 0;

for (var word : words) {

boolean canType = true;

for (int i = 0; i < word.length(); i++) {

if (Arrays.binarySearch(brL, word.charAt(i)) >= 0) {

canType = false;

break;

}

}

if (canType) {

canTypeCnt++;

}

}

return canTypeCnt;

}

}

Success:

Runtime:2 ms, faster than 91.93% of Java online submissions.

Memory Usage:42.7 MB, less than 23.23% of Java online submissions.

Оригинал.

Показать полностью
22

GitLab: склонировать список репозиториев

Решил слегка “причесать” и обобщить свой опыт по этому вопросу. Чтобы удобней было пользоваться, как этакой краткой инструкцией, а не искать разрозненные ответы на SO и т.п.

Задача проста – сделать удобно.

  1. Взять GitLab (много где используется, как self-hosted) и выкачать с него все репозитории проекта. Чтобы можно было локально работать с ними, не загружая каждый отдельно.

  2. Обновлять эти репозитории одной командой

Загрузка списка репозиториев с GitLab

Тут всё несложно – надо получить сам список и по нему всё скачать. Удобнее это делать с использованием ssh ключа (добавляется в GitLab через веб-интерфейс). Но можно и git credentials включить. Сам список достаточно просто в браузере открыть и сохранить projects.json (название по умолчанию).

  • Список репозиториев: https://your-gitlab-host/api/v4/projects?per_page=1000

  • Или список для группы проектов: https://your-gitlab-host/api/v4/groups/{group-id}/projects?per_page=1000

group-id можно тоже через веб-интерфейс посмотреть, примерно так:

GitLab: склонировать список репозиториев
  • Выкачать (в текущий каталог) репозитории по списку из файла: jq -r '.[].ssh_url_to_repo' < /path/to/projects.json | xargs -n1 git clone. Можно аналоги утилиты jq использовать, мне она привычней.

  • Если авторизация по ssh-ключу не настроена – придется из json вместо поля ssh_url_to_repo извлекать поле http_url_to_repo. Можно хранить логин/пароль для GitLab в ~/.git-credentials (там они лежат в открытом виде!).

Первая часть на этом закончена. На очереди – обновление репозиториев.

Обновление списка репозиториев

Здесь всё ещё проще – достаточно одной команды. Перейти в каталог со склонированными репозиториями и выполнить:

find . -type d -name '.git' \

| xargs -n1 -- sh -c \

'cd "${0}/.." && echo \

&& basename -sa $(git rev-parse --show-toplevel) \

&& git pull --all'

Найдёт все каталоги с директорией .git внутри (а это и есть репозитории) и обновит их через git pull --all. Соответственно, каталоги, не являющиеся репозиториями, будут проигнорированы.

Показать полностью 1
2

LeetCode 13. Roman to Integer

Приятная задачка выпала в поиске – хоть и easy, а сделать интересно. Какая-то “практическая применимость” в ней видится.

Вроде, там где-то и обратная проблема была – перевод записи арабскими цифрами в запись римскими.

В общем-то, список валидных префиксов там прямо в условии задачи описан, особо выдумывать тут ничего не требуется.

LeetCode 13. Roman to Integer

Можно ещё вариант со switch-case сделать, но там с валидацией порядка цифр в записи будут вопросы. Реализация со словарём префиксов их снимает автоматом.

Оригинал.

Показать полностью
7

Git config с разделением по проектам

Возникла потребность настраивать по-разному конфиги гита для разных проектов (email контактный поменять, хотя бы, или хук на прогон тестов повесить).

Ну и понятно, что как-то эти конфиги подкладывать туда-сюда – не слишком увлекательно. К счастью, в свежих версиях гита – есть инклюды. В том числе – по условию – includeIf. Вот ими и стоит воспользоваться.

Основной конфиг git

Общая концепция такова – в основном конфиге ~/.gitconfig – перечислить (под условиями) конфиги “зависимые”, а все специфичные настройки прописать уже в них. Ничего экстраординарного, в общем.

Примерно вот так у меня это выглядит, по условию включается конфиг из файла gitconfig-project-1:

[user]

name = Dmitry

email = dimio@dimio.org

[includeIf "gitdir:~/project-1/repos/"]

path = ~/.config/git/gitconfig-project-1

Важный момент – директорию после gitdir: нужно указывать без отделения пробелом.

Вложенный конфиг git

А вот так – выглядит сам файл ~/.config/git/gitconfig-project-1

[user]

email = dmitry@dimio.org

[core]

hooksPath = ~/.config/git/hooks/

autocrlf = input

sshCommand = "ssh -F ${HOME}/.ssh/config-project-1"

Тут уже как раз и переопределены email, хуки (для этого проекта активирован автопрогон тестов в pre-push хуке) и конфиг ssh (там специфические настройки для доступа к репозиторию по ключу).

Разделение credentials

Раз уж зашла речь о разделении конфигов и о доступе – можно сразу настройки доступа по http(s) разбить немного.

Включаются они так: git config --global credential.helper store. И после этого лежат в ~/.git-credentials в открытом виде!

Разделить их для разных репозиториев внутри одного хоста – можно так (на примере github): git config --global credential.github.com.useHttpPath true

И тогда в .git-credentials будут отдельные записи лежать:

https://<USERNAME>:<PASSWORD>@github.com/path/to/repo1.git

https://<USERNAME>:<PASSWORD>@github.com/path/to/repo2.git

Но, безусловно, удобней (да и безопасней, пожалуй) – пользоваться доступом с ssh ключами.

Показать полностью
93

CloudFlare WARP + WireGuard через NetworkManager1

Долгое время пользовался ssh-туннелем для «разблокировки» некоторых сетевых ресурсов, доступ к которым был ограничен для IP Российского диапазона (ну, драйверы там скачать с сайта производителя, и т.п.).

Но — всему приходит конец. Моему терпению — тоже. Надоело постоянно переключать потребителей на работу через прокси (privoxy), чтобы завернуть трафик в socks-прокси туннеля. TOR стали прикручивать, что привело к очень долгому поиску мостов. И лень моя победила (в очередной раз).

Очевидно — нужен был способ попроще, да ещё — без особых затрат. Ставить VPN сервер (в том или ином виде) на VPS — хотелось ещё меньше, чем кидать туннель. Всякие платные прокси (типа Mullvad) — они удобны, позволяют выбрать «точку выхода», но — надо изыскивать возможность их оплатить. Бесплатные — обычно, работают так себе.

Тут я вспомнил, что есть же CloudFlare и его WARP, причем — в бесплатной версии, да со всей мощью клаудфлэровских серверов, да без ограничений скорости, да ещё и — должен, теоретически, работать через нативный клиент WireGuard. «Надо попробовать» — подумал Штирлиц.

Настройка WARP в Linux

В целом, процесс достаточно понятный, на современных системах — проблем быть не должно (на современных — это где Network Manager поддерживает WireGuard, иначе — можно и через консоль поднимать/гасить интерфейс VPN, но это менее удобно).

  • Сгенерировать конфиг для WARP — консольной утилитой или онлайн-генератором на её базе. Ещё есть неофициальный CLI, мне он не пригодился.

  • Полученный конфиг можно сунуть в /etc/wireguard/ и попробовать поднять через systemctl start wg-quick@название-конфига.conf. Но вряд ли это заработает, конфиг придется править.

Конфиг WireGuard для WARP

А чтобы не править его, передергивая интерфейс вручную из консоли, — проще сразу добавить в Network Manager. Подобрать рабочие настройки там, затем — перенести в конфиг. И получить основной (через графический интерфейс) и резервный (из консоли) способы работы с WARP. Чем и займёмся.

Настройка Network Manager

Тут всё тоже несложно: ПКМ на аплете менеджера — Соединения VPN — Настроить VPN — WireGuard — ‘+’ (добавить новое соединение).

Дальше настроить по картинке (скопировать значения из файла конфига):

Но вот адрес для Endpoint придется поподбирать — на разных провайдерах работают разные IP. Я прошелся по адресам с 162.159.193.0 по 162.159.193.10, пока не нашел работающий.

В целом — соединение уже должно работать (надо только Address в Параметры IPv4 вписать, как ниже показано), проверить можно через 2ip.ru. Вот такая картина у меня:

Подключается не всегда с первого раза, бывает, нужно несколько раз вкл/выкл VPN.

Google DNS и Wire Guard WARP

Но радость была бы не полной, если бы не ещё одна чудесная возможность WireGuard — он позволяет для соединения легко поменять адрес DNS сервера. Это не защитит от утечки DNS на сто процентов, но позволяет обойти блок, выставляемый на некоторых ресурсах на основе географической принадлежности DNS сервера (а клаудфлэровский — в Москве).

В настройки IPv4 надо вписать гугловый DNS, в настройки IPv6 — можно по аналогии (IPv6-адрес DNS ищется в гугле же), а можно и обойтись только IPv4.

WireGuard Google public DNS

Итого

Вот теперь «разблокировка» должна работать нормально.

Из плюсов — VPN включается сразу на уровне системы, приложения ходят через него. Не надо, как в случае с ssh-туннелем, заворачивать приложения для работы с через туннель.

Второй плюс — ровно тем же способом можно включить WARP на Android. Клиент WireGuard под Android есть (ставил из F-Droid), надо только поправить сгенерированный конфиг по аналогии (как в заметке), затем — импортировать его в клиенте на телефоне. Всё!

Следующим шагом — можно настроить подключение WARP на роутере, чтобы всю внутреннюю сеть пускать в интернет через VPN. Я на своём Keenetic планирую так и сделать, но это «уже совсем другая история».

Показать полностью 3

Leetcode 1920. Build Array from Permutation

После долгих праздничных выходных — приходится «разогревать» голову задачками с высоким Acceptance. И даже они — не сразу заходят. Со скрипом.


class Solution { public static int[] buildArray(int[] nums) { int[] ans = new int[nums.length]; for (int i = 0; i < nums.length; i++) { ans[i] = nums[nums[i]]; } return ans; } }


https://leetcode.com/problems/build-array-from-permutation/d...

Отличная работа, все прочитано!