Cesta sorpresa - Ahorre nuestro empuje

TLDR: creó un conjunto de scripts que automatizaron la migración de repositorios de Bitbucket de Mercurial a Git.

Un buen día, mi servicio de alojamiento de repositorios Bitbucket favorito anunció que pronto dejaría de admitir los repositorios de Mercurial en favor de Git, después de lo cual se eliminarían todos los repositorios de Mercurial.

imagen

Tengo muchos repositorios privados de Mercurial en Bitbucket, no quería perderlos, al igual que su historial de confirmaciones. Mudarse a otro alojamiento tampoco es una opción: estoy acostumbrado a Bitbucket. Los propios Bitbucket, por extraño que parezca, no pudieron hacer un convertidor en el lugar. Ni siquiera escribieron instrucciones paso a paso para la conversión, enviando a todos al foro de su comunidad , con una redacción bastante jesuita (Estamos felices de apoyar su migración, y puede encontrar una discusión sobre las opciones disponibles en nuestro hilo dedicado de la Comunidad) - dicen Nos complace mover sus repositorios en Git, y cómo hacerlo: hable usted mismo en el foro. Sin embargo, en la misma publicación dejaron enlaces a un par de convertidores hg-fast-export y hg-git .

El primero es un script de Python separado, el segundo es un complemento para trabajar con repositorios Git directamente desde Mercurial. Google también encontró varios ejemplos de cómo otros resolvieron la tarea de arrastrar y soltar Mercurial bajo Git: lo , behold y lo . También usaron hg-fast-export o hg-git. La segunda ya era una solución probada para mí: solía usar hg-git a veces cuando me comprometía con Github de Mercurial, hasta que me di cuenta de que en Git, curiosamente, es mejor comprometerse con Git. Entonces, para mis propósitos, elegí hg-git.

aquíSe proporciona un script de Powershell para automatizar la migración del repositorio, que fue el punto de partida de mi solución, pero para Linux tuve que reescribirlo en Bash. Además, el script original solo migra al repositorio local de Git, y agregué la capacidad de enviar los contenidos del repositorio Git convertido al repositorio de Bitbucket allí. Así es como se ve el 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 

Ahora tenía una solución preparada, pero requería acciones manuales; antes de lanzarla, era necesario crear primero un repositorio Git en Bitbucket, para que hubiera dónde impulsar el resultado. Al mirar mis 100,500 repositorios para convertir, me di cuenta de que los procesaría durante mucho tiempo, me gustaría que el script creara repositorios Git para los convertidos, y aún mejor, recibiría una lista de mis repositorios Mercurial y trabajaría en ello. Esto claramente fue más allá de la habilidad de Mercurial puro, aquí se requería la funcionalidad del propio Bitbucket, o más bien la API de Bitbucket .

Hay bibliotecas listas para usar con la API de Bitbucket para varios lenguajes de programación, en particular para Python, aparentemente el SDK oficial(no debe confundirse con el SDK abandonado hace mucho tiempo, pero una vez no menos oficial que yace en Bitbucket ). También hay clientes API de Bitbucket para Java , NodeJS y PHP . El último que elegí.

Sin embargo, cuando se estudió en detalle, resultó que no se implementó para obtener una lista de repositorios de usuarios y crear un nuevo repositorio. Afortunadamente, los creadores de la biblioteca proporcionaron la posibilidad de expandir sus clases haciendo que los métodos privados estén protegidos, de modo que al heredar la clase de su cliente API, podría agregar sus propios métodos que hacen lo que necesito:

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);
    }
}

Después de eso, escribí un par de scripts PHP y otro script Bash para ejecutarlos, y después de una hora ya podía admirar una computadora pegada a mí:

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, la conversión tardó aproximadamente una hora en funcionar, después de lo cual ahora estoy examinando los repositorios Git convertidos en segundo plano para asegurarme de que no se pierda nada. Y solo después de eso elimino los repositorios originales de Mercurial con mis manos. Por supuesto, nada impide agregar una eliminación del repositorio de Bitbucket Mercurial después de la conversión al script, pero en mi opinión, este es solo el caso cuando la automatización excesiva puede dañar. Aquí

hay un conjunto de scripts listos para usar para automatizar la migración del repositorio P.S .:

Aprovechando esta oportunidad, plantearé la pregunta retórica: ¿por qué es Git, que a veces funciona con una lógica bastante obvia, mucho más popular que el Mercurial, mucho más lógico, en el que simplemente te comprometes, creas ramas y, si algo sale mal, revierte los compromisos sin pensar en ello? ¿Qué hay debajo del capó del sistema de control de versiones y sobre el puntero a Head, pero solo haciendo lo que necesita? En mi opinión, esto es injusto, porque lo obvio es mejor que lo no obvio, y es muy triste que Bitcurket, uno de los pilares de resistencia a la corriente principal en los sistemas de control de versiones, deje de admitir Mercurial.

All Articles