Cesta Surpresa - Save Our Push

TLDR: Criou um conjunto de scripts automatizando a migração de repositórios Bitbucket do Mercurial para o Git.

Um belo dia, meu serviço de hospedagem de repositório Bitbucket favorito anunciou que em breve deixaria de oferecer suporte aos repositórios Mercurial em favor do Git, após o qual todos os repositórios Mercurial seriam excluídos.

imagem

Eu tenho muitos repositórios particulares do Mercurial no Bitbucket, não queria perdê-los, assim como o histórico de confirmação deles. Mudar para outra hospedagem também não é uma opção - estou acostumado ao Bitbucket. O próprio Bitbucket, por incrível que pareça, não foi capaz de fazer um conversor no local. Eles nem sequer escreveram instruções passo a passo para a conversão, enviando todos para o fórum de sua comunidade - com uma expressão bastante jesuíta (estamos felizes em apoiar sua migração e você pode encontrar uma discussão sobre as opções disponíveis em nosso dedicado tópico da comunidade) - eles dizem Estamos felizes em mover seus repositórios no Git, e como fazer isso - discuta você mesmo no fórum. No entanto, no mesmo post, eles deixaram links para um par de conversores hg-fast-export e hg-git .

O primeiro é um script Python separado, o segundo é um plugin para trabalhar com repositórios Git diretamente do Mercurial. O Google também encontrou vários exemplos de como os outros resolviam a tarefa de arrastar e soltar o Mercurial no Git: lo , behold e lo . Eles também usaram hg-fast-export ou hg-git. A segunda já era uma solução comprovada para mim - eu costumava usar o hg-git às vezes quando me comprometia com o Github da Mercurial - até que percebi que no Git, por incrível que pareça, é melhor se comprometer com o Git. Então, para meus propósitos, escolhi o hg-git.

AquiÉ fornecido um script do Powershell para automatizar a migração do repositório, que foi o ponto de partida da minha solução, mas no Linux eu tive que reescrevê-lo no Bash. Além disso, o script original migra apenas para o repositório Git local, e eu adicionei a capacidade de enviar o conteúdo do repositório Git convertido para o repositório Bitbucket. Aqui está a aparência do script resultante:

$ ./convert_repo.sh lebedevsergey advertisements_parser
2a51eee7ade0
requesting all changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 5 changes to 5 files
updating to branch default
5 files updated, 0 files merged, 0 files removed, 0 files unresolved
Initialized empty Git repository in /home/serge/project/_probes/hg2git/src/advertisements_parser-git/
pushing to ../advertisements_parser-git
searching for changes
adding objects
added 1 commits with 2 trees and 5 blobs
error: Could not remove config section 'remote.origin'
Branch master set up to track 

Agora eu tinha uma solução pronta, mas exigia ações manuais - antes de iniciá-la, era necessário primeiro criar um repositório Git no Bitbucket, para que houvesse onde empurrar o resultado. Olhando para os meus 100.500 repositórios a serem convertidos, percebi que os processaria por um longo tempo, gostaria que o próprio script criasse repositórios Git para os convertidos e, melhor ainda - receberia uma lista dos meus repositórios Mercurial e trabalharia nele. Isso claramente foi além da habilidade do Mercurial puro, aqui a funcionalidade do próprio Bitbucket, ou melhor, da API do Bitbucket , era necessária .

Existem bibliotecas prontas para trabalhar com a API Bitbucket para várias linguagens de programação, em particular para Python - aparentemente o SDK oficial(para não ser confundido com o SDK há muito abandonado, mas uma vez não menos oficial que está no próprio Bitbucket ). Também existem clientes da API do Bitbucket para Java , NodeJS e PHP . O último que eu escolhi.

No entanto, quando foi estudado em detalhes, descobriu-se que não foi implementado para obter uma lista de repositórios de usuários e criar um novo repositório. Felizmente, os criadores da biblioteca forneceram a possibilidade de expandir suas classes, protegendo os métodos privados, para que, ao herdar a classe do cliente da API, você pudesse adicionar seus próprios métodos, que fazem o que eu preciso:

class ExtendedClient extends Client
{
    /**
     * @return \Bitbucket\Api\Repositories
     */
    public function repositories()
    {
        return new ExtendedRepositories($this->getHttpClient());
    }
}

class ExtendedRepositories extends Repositories
{    
    public function listWorkspace(string $workspaceName, array $params = [])
    {
        $path = $this->buildRepositoriesPath($workspaceName);
        return $this->get($path, $params);
    }

    public function create(string $workspaceName, string $repoName, array $params = [])
    {
        $path = $this->buildRepositoriesPath($workspaceName, $repoName);

        return $this->post($path, $params);
    }
}

Depois disso, escrevi alguns scripts PHP e outro script Bash para executá-los, e depois de uma hora eu já podia admirar um computador que me atrapalhava:

Checking repository: mysett
Trying to create Git repository: git_mysett
Created Git repository: git_mysett
20abecfb36fe
applying clone bundle from https://api.media.atlassian.com/file/4d5980dc-148f-400c-97f7-8067506778a5/binary?client=403e8d2f-6661-452a-8307-5c68f82c1a13&token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3MiOnsidXJuOmZpbGVzdG9yZTpmaWxE2bUg7aRIzuKbjwOn5SF8IbGEVs33WHDVb-JYto
adding changesets
adding manifests
adding file changes
added 27 changesets with 56 changes to 41 files
finished applying clone bundle
searching for changes
no changes found
updating to branch default
35 files updated, 0 files merged, 0 files removed, 0 files unresolved
Initialized empty Git repository in /home/serge/project/hg2git/src/mysett-git/
pushing to ../mysett-git
searching for changes
adding objects
added 27 commits with 82 trees and 50 blobs
error: Could not remove config section 'remote.origin'
Counting objects: 159, done.
Delta compression using up to 12 threads.
Compressing objects: 100% (133/133), done.
Writing objects: 100% (159/159), 12.95 MiB | 7.95 MiB/s, done.
Total 159 (delta 0), reused 159 (delta 0)
To git@bitbucket.org:lebedevsergey/git_mysett.git
 * [new branch]      master -> master
Branch master set up to track remote branch master from origin.
Checking repository: jazzz
Trying to create Git repository: git_jazzz

Como resultado, a conversão levou cerca de uma hora para funcionar, após o que agora estou navegando nos repositórios Git convertidos em segundo plano para garantir que nada foi perdido. E somente depois disso eu apago os repositórios originais do Mercurial com as mãos. Obviamente, nada impede a adição de uma remoção do repositório Bitbucket Mercurial após a conversão no script, mas, na minha opinião, esse é apenas o caso em que a automação excessiva pode danificar.

Um conjunto de scripts prontos para automatizar a migração do repositório está localizado aqui

P.S .:Aproveitando esta oportunidade, levantarei a questão retórica - por que o Git, que às vezes funciona com lógica bastante óbvia, muito mais popular do que o Mercurial muito mais lógico, no qual você apenas confirma, cria ramificações e, se algo der errado, reverte as confirmações sem pensar em o que há sob o capô do sistema de controle de versão e o ponteiro para o Head, mas apenas o que você precisa? Na minha opinião, isso é injusto, porque o óbvio é melhor que o não óbvio, e é muito triste que o Bitcurket, um dos pilares de resistência ao mainstream nos sistemas de controle de versão, pare de dar suporte ao Mercurial.

All Articles