Baixando e atualizando programas de terceiros no Arch Linux direto da fonte (sem AUR)

O que eu digo aqui pode ser aplicado a muitos programas que disponibilizam pacotes oficiais para Arch/Manjaro se você estiver disposto a experimentar (ou mesmo em outras distribuições cujos gerenciadores de pacotes suportem repositórios localizados dentro do disco).

Etapa 1 – repositório personalizado

A base do procedimento aqui, é fazer o pacman buscar pacotes já dentro do seu sistema de arquivos. Há um mecanismo nele para isso, descrito em detalhes nessa página da Wiki.

O essencial é:

  1. Crie uma pasta vazia (ex: /home/usuario/pasta) em qualquer lugar do seu sistema.
  2. Coloque o primeiro pacote do programa que você quer atualizar direto da fonte nessa pasta. Baixe-o manualmente, depois vamos automatizar esse processo. Digamos, exemplo-1.0-1.pkg.tar.xz.
  3. Abra um terminal nessa pasta e rode repo-add "meurepositorio.db.tar.xz" "exemplo-1.0-1.pkg.tar.xz"
  4. Seu repositório personalizado começou, e agora tem o primeiro pacote.

Para fazer o pacman buscar pacotes nele, edite /etc/pacman.conf e acrescente:

[meurepositorio]
SigLevel = Optional TrustAll
Server = file:///home/usuario/pasta

Substitua:

  • meurepositorio pelo nome do arquivo .db.tar.xz (sem as extensões) que você criou no passo 3,
  • /home/usuario/pasta pelo caminho da pasta criada no passo 1 (deixe o file://)

Agora, essa pasta vai ser um dos locais onde pacman busca atualizações durante o famoso pacman -Syu, bastando rodar repo-add PACOTE meurepositorio.db.tar.xz para “notificar” a existência do pacote.

Etapa 2, 3, 4, 5, etc. – Adicionando pacotes

Caso 1 – Pacotes com link fixo

Para isso, vamos pegar o exemplo do Zoom.

O link de download do Zoom para Arch Linux, se pegamos do site, é:
https://zoom.us/client/latest/zoom_x86_64.pkg.tar.xz
Pelo link, dá para ver que o link é relativo à latest, ou sempre à última versão.

A maneira mais simples de criar garantir sua atualização seria o seguinte shell script:

#!/bin/bash
# Entrar na pasta do repositório.
# || exit 1 → se não for possível entrar na pasta (comando antes do ||), sair com erro.
cd /home/usuario/pasta || exit 1
# wget - baixar um arquivo, -O especificar a saída, -q não mostrar o progresso
# comando1 && comando2 - se o comando1 retornar sucesso, rodar o comando2
wget -qO "zoom.pkg.tar.xz" "https://zoom.us/client/latest/zoom_x86_64.pkg.tar.xz" &&
repo-add "meurepositorio.db.tar.xz" "zoom.pkg.tar.xz"

Com systemd-timers ou cron, é possível, por exemplo, rodar esse script a dia, mês ou semana. E o pacman pode pegar arquivos baixados por ele durante o -Syu.

O script como está até agora é um pouco “gastador”, (por exemplo, ele apenas baixa sem verificar se realmente há uma versão nova, e se houver alguma falha no download, o arquivo antigo será sobrescrito pela versão incompleta), mas é um começo.

Caso 2 – Extrair o link de um site com a lista de versões

Se você tiver uma página com a lista de versões do programa, dá para automatizar o procedimento de download com nossas clássicas ferramentas de terminal (grep, head, etc.), combinadas com o wget (que eu apresentei lá em cima) e um extrator de informações (parser) de HTML (nesse exemplo vou usar o pup, mas há também o htmlq). Ou, se você preferir, Python. Ou se você é nostálgico pelos anos 90, perl + libwww. Enfim, vou colocar a versão com ferramentas de terminal, usando de exemplo o Wine-TKG, mais especificamente a lista de versões:

A primeira etapa é obter o conteúdo da página, para extrair dele os links. Eu apresentei o wget com a opção -O lá em cima. Se colocar - (em vez de um nome de arquivo) depois do O, a saída do wget vai para o terminal:

wget -qO - "https://github.com/Frogging-Family/wine-tkg-git/releases"
<!DOCTYPE html>
<html lang="en" data-color-mode="auto" data-light-theme="light" data-dark-theme="dark">
  <head>
    <meta charset="utf-8">
  <link rel="dns-prefetch" href="https://github.githubassets.com">
  <link rel="dns-prefetch" href="https://avatars.githubusercontent.com">
  <link rel="dns-prefetch" href="https://github-cloud.s3.amazonaws.com">
  <link rel="dns-prefetch" href="https://user-images.githubusercontent.com/">
[... sério, muita coisa]

Do jeito que ele está agora, o link para o arquivo provavelmente está por aí no meio dessa bagunça. Talvez um outro comando facilite achar o link nela… É justamente o que um parser de HTML pode fazer, como o pup que eu citei.

Usando o |, podemos passar a saída do wget -qO - para a entrada de outro comando, . Nesse caso, o pup, com o parâmetro 'a attr{href}', extrai os links da página:

$ wget -qO - "https://github.com/Frogging-Family/wine-tkg-git/releases" | pup 'a attr{href}'
#start-of-content
https://github.com/
/join?ref_cta=Sign+up&amp;ref_loc=header+logged+out&amp;ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Freleases%2Findex&amp;source=header-repo
/features
[....]

Ok, ainda tem um monte de coisa irrelevante. No entanto, podemos filtrar essa saída com com o grep.

$ wget -qO - "https://github.com/Frogging-Family/wine-tkg-git/releases" | pup 'a attr{href}' | grep '.pkg.tar.zst'
/Frogging-Family/wine-tkg-git/releases/download/6.8.r0.g0f00e37c/wine-tkg-staging-fsync-git-6.8.r0.g0f00e37c-326-x86_64.pkg.tar.zst
/Frogging-Family/wine-tkg-git/releases/download/6.7.r0.gdeed76f3/wine-tkg-staging-fsync-git-6.7.r0.gdeed76f3-326-x86_64.pkg.tar.zst
/Frogging-Family/wine-tkg-git/releases/download/6.5.r1.g2e42e7d9/wine-tkg-staging-fsync-git-6.5.r1.g2e42e7d9-322-x86_64.pkg.tar.zst
/Frogging-Family/wine-tkg-git/releases/download/6.4.r0.g7ec998e1/wine-tkg-staging-fsync-git-6.4.r0.g7ec998e1-322-x86_64.pkg.tar.zst

Agora é só coisa relevante. Melhor ainda, vem na ordem que eles apareceram na página, na qual o primeiro é o mais novo. Para obter o primeiro, pode-se usar head -nX pega as X primeiras linhas. Como queremos a 1ª, head -n1:

$ wget -qO - "https://github.com/Frogging-Family/wine-tkg-git/releases" | pup 'a attr{href}' | grep '.pkg.tar.zst' | head -n1
/Frogging-Family/wine-tkg-git/releases/download/6.8.r0.g0f00e37c/wine-tkg-staging-fsync-git-6.8.r0.g0f00e37c-326-x86_64.pkg.tar.zst

Em alguns casos, como esse, o link vem com uma parte omitida. O problema é que o navegador sabe que tem que colocar https://github.com no começo, mas nosso script não.

Contudo, dá para dizer isso para o script. Podemos armazenar a saída desse comando em uma variável no script, usando $(), e então rodar um segundo wget tento como parâmetro "https://github.com/$VARIAVEL" (ou seja, “https://github.com/ e $ubstitua essa parte com a VARIAVEL”):

#!/bin/bash
cd /home/usuario/pasta || exit 1
ARQUIVO=$(wget -qO - "https://github.com/Frogging-Family/wine-tkg-git/releases" | pup 'a attr{href}' | grep '.pkg.tar.zst' | head -n1)
wget -qO "wine-tkg.tar.xz" "https://github.com/$ARQUIVO" && repo-add "meurepositorio.db.tar.xz" "wine-tkg.tar.xz"

Novamente, com um temporizador, dá para rodar isso semanalmente ou mensalmente, garantido um nível de atualidade que rivaliza o Bomba Patch (apesar de isso ainda poder ter os mesmos defeitos do primeiro script).


Notas de rodapé
  1. Se você não tiver o comando Wget no seu sistema, mas tiver o curl, pode usar:
    • curl -s [SITE] em vez de wget -qO - [SITE]
    • curl -s -o [ARQUIVO] [SITE] em vez de wget -qO [ARQUIVO] [SITE].
  2. Para esse tópico não ficar mais complicado do que já é, as sugestões para melhorar a eficiência (verificar versão, fazer backup da versão antiga antes de baixar a nova, etc.) ficam como um exercício para o leitor. Se houver um interesse, posso fazer um apêndice com como fazer isso.
  3. Quem é mais experiente no terminal viu várias “micromelhorias” que podem ser feitas nos exemplos que eu dei, como usar grep -Fm1, criar funções para automatizar partes repetidas, etc., mas isso pode ser aprendido em tutoriais mais gerais de shellscript.
  4. Sei que o GitHub disponibiliza um arquivo JSON para obter as versões e links de downloads dos programas (e isso poderia ser utilizado no exemplo), mas não desejo o jq para muitas pessoas. Com um conhecimento adequado das APIs para analisar JSON e baixar arquivos em outras linguagens de programação, no entanto, é trivial fazer a mesma automação em outras linguagens, apenas utilizando system("repo-add \Q$pacote\E meurepositorio.db.tar.xz"); no final ou equivalente.
10 curtidas

Você realmente me pegou. Fiquei vinte e dois minutos tentando acessar o site, para tentar descobrir que raios é meuprograma.

2 curtidas