Skip to content

Latest commit

 

History

History
365 lines (304 loc) · 13.4 KB

import-custom.asc

File metadata and controls

365 lines (304 loc) · 13.4 KB

Un proveedor individual

Si su sistema no es uno de los arriba mencionados, usted debe buscar un importador online - importadores de calidad están disponibles para muchos otros sistemas, incluido el CVS, Clear Case, Visual Source Safe, incluso un directorio de archivos. Si ninguna de estas herramientas funciona para usted, tiene una herramienta más obsoleta o necesita un método de importación más personalizado, debería usar `git fast-import'.. Este comando lee instrucciones simples de stdin para escribir datos Git específicos. Es mucho más fácil crear objetos Git de esta manera que ejecutar los comandos raw Git o intentar escribir los objetos raw (ver <ch10-git-internals.asc para más información). De esta manera, puede escribir un script de importación que lee la documentación necesaria del sistema desde el que está cargando e imprime instrucciones directas a stdout. A continuación, puede ejecutar este programa y canalizar su resultado mediante `git fast-import

Para demostrar rápidamente, podrá escribir un simple mensaje Supongamos que trabajas en current, haces una copia de seguridad de tu proyecto copiando el directorio ocasionalmente en un directorio de copia de seguridad con el código ‘back_YYYY_MM_DD" directorio de copia de seguridad y desea importar esta en Git. Tu Estructura del directorio se ve así:

$ ls /opt/import_from
back_2014_01_02
back_2014_01_04
back_2014_01_14
back_2014_02_03
current

Para poder importar un directorio Git, necesitas revisar cómo Git almacena sus datos. Como recordará, Git es fundamentalmente una listado enlazado de objetos commit que apuntan a una imágen de contenido. Todo lo que tienes por hacer es indicarle a `fast-import`qué son las snapshots de contenido, cuáles son los puntos de datos de confirmación y el orden en que van a entrar. Su estrategia será para ir a través de snapshots Uno a la vez y crear commits con el contenido de cada directorio, vinculando cada commit al anterior.

Como hicimos en ch08-customizing-git.asc, scribiremos esto en Ruby, porque es con lo que generalmente trabajamos y tiende a ser fácilmente legible.Usted puede escribir este ejemplo con bastante facilidad en cualquier elemento con el que esté familiarizado - sólo tiene que escribir la información apropiada a "stdout"., si se está ejecutando en Windows, esto significa que usted tendrá que tener especial cuidado de no introducir porte devoluciones al final de sus líneas - Importación rápida de git es muy particular acerca de que sólo quieren saltos de línea (LF) salto de línea (CRLF) usando windows.

Para empezar, cambiará al directorio de destino e identificará cada subdirectorio, cada uno de los cuales es snapshot que desea importar como un commit. Cambiará a cada subdirectorio e imprimirán los comandos necesarios para exportarlo. Tu loop principal básico se ve así:

last_mark = nil

# loop through the directories
Dir.chdir(ARGV[0]) do
  Dir.glob("*").each do |dir|
    next if File.file?(dir)

    # move into the target directory
    Dir.chdir(dir) do
      last_mark = print_export(dir, last_mark)
    end
  end
end

Si ejecuta print_export dentro del directorio, que toma el registro y la señal de la instantánea anterior y devuelve el registro y la señal de ésta; de esa manera, se pueden enlazar correctamente.`Mark'' is the `fast-import para un código de identificación que se da a un commit; mientras crea commits,dar a cada uno de ellos una anotación que se puede utilizar para vincular al mismo desde otro commits. Por lo tanto, lo primero que debe hacer en el método `print_export' es generar una etiqueta a partir del nombre del directorio:

mark = convert_dir_to_mark(dir)

Para ello, creará una matriz de directorios y utilizará el valor índice como punto, ya que una línea debe ser un código entero. Tu sistema se ve así:

$marks = []
def convert_dir_to_mark(dir)
  if !$marks.include?(dir)
    $marks << dir
  end
  ($marks.index(dir) + 1).to_s
end

Ahora que tiene una representación entera de su commit, necesita una dirección para los metadatos de commit. Como la información está expresada en el nombre del directorio, la analizarás. La siguiente línea del archivo print_export es

date = convert_dir_to_date(dir)

Donde`convert_dir_to_date` esta definido como

def convert_dir_to_date(dir)
  if dir == 'current'
    return Time.now().to_i
  else
    dir = dir.gsub('back_', '')
    (year, month, day) = dir.split('_')
    return Time.local(year, month, day).to_i
  end
end

Esto devuelve un valor entero para la data de cada directorio. La última parte de la meta-información que necesita para cada committer son los datos del committer, que usted codifica en una variable global:

$author = 'John Doe <[email protected]>'

Ahora está listo para empezar a publicar los datos de validación para su importador.: La información inicial indica que está definiendo un objeto de commit y en qué rama está activado, seguido de la línea que ha generado, la información de committer y el mensaje de committer y, a continuación, la línea anterior, si la hay. El código se ve así:

# print the import information
puts 'commit refs/heads/master'
puts 'mark :' + mark
puts "committer #{$author} #{date} -0700"
export_data('imported from ' + dir)
puts 'from :' + last_mark if last_mark

Usted codifica la zona horaria (-0700) porque hacerlo es fácil.

Si está importando desde otro sistema, debe especificar el uso horario como un intervalo de tiempo. El mensaje de confirmación debe expresarse en un formato especial:

data (size)\n(contents)

El formato consiste en los datos de la palabra, el tamaño de los datos a leer, una nueva línea, y finalmente los datos. Puesto que necesita utilizar el mismo formato para especificar el contenido del archivo más tarde, cree un sistema de ayuda,"export_data":[source,ruby]

def export_data(string)
  print "data #{string.size}\n#{string}"
end

Todo lo que queda es especificar el contenido del archivo para cada uno de ellos. snapshot. Esto es fácil, porque tiene cada uno de ellos en un directorio - puede crear el comando borrar todo seguido del contenido de cada archivo en el directorio. Git entonces grabará cada instantánea apropiadamente:

puts 'deleteall'
Dir.glob("**/*").each do |file|
  next if !File.file?(file)
  inline_data(file)
end

Nota: Porque muchos sistemas piensan que sus modificaciones son cambios de una confirmación a otra, fast-import también puede tomar comandos con cada confirmación para especificar qué archivos se han agregado, eliminado o modificado y cuáles son los nuevos archivos. Podrías calcular las diferencias entre snapshots y proporcionar sólo estos archivos, pero hacerlo es más complejo - también puedes darle a Git todos los datos y dejar que lo resuelva. Si esto se adapta mejor a sus archivos, consulte la página de manual "Importación rápida" para obtener más detalles sobre cómo proporcionar sus archivos de esta manera. El formato para listar el nuevo contenido del archivo o especificar un archivo modificado con el nuevo contenido es el siguiente:

M 644 inline path/to/file
data (size)
(file contents)

Aquí, 644 es el modulo (si tiene archivos ejecutables, necesita detectar y especificar 755 en su lugar), e inline dice que listará el archivo inmediatamente después de esta línea. Su método de "datos_inline" se ve así:

def inline_data(file, code = 'M', mode = '644')
  content = File.read(file)
  puts "#{code} #{mode} inline #{file}"
  export_data(content)
end

Se reutiliza el modo export_data que definió anteriormente, porque es el mismo que el de los datos del mensaje de confirmación. Lo último que necesita hacer es devolver la línea actual para que pueda pasar a la siguiente edición:

return mark
Note

Si se está ejecutando en Windows, deberá asegurarse de añadir un paso más. Como se ha dicho antes, Windows utiliza CRLF para nuevos carácteres de línea, mientras que git fast-import sólo espera LF. Para solucionar este problema y hacer git fast-importar feliz, necesita decirle a ruby para utilizar LF en lugar de CRLF:

$stdout.binmode

Eso es todo. Aquí está el script en su totalidad:

#!/usr/bin/env ruby

$stdout.binmode
$author = "John Doe <[email protected]>"

$marks = []
def convert_dir_to_mark(dir)
    if !$marks.include?(dir)
        $marks << dir
    end
    ($marks.index(dir)+1).to_s
end


def convert_dir_to_date(dir)
    if dir == 'current'
        return Time.now().to_i
    else
        dir = dir.gsub('back_', '')
        (year, month, day) = dir.split('_')
        return Time.local(year, month, day).to_i
    end
end

def export_data(string)
    print "data #{string.size}\n#{string}"
end

def inline_data(file, code='M', mode='644')
    content = File.read(file)
    puts "#{code} #{mode} inline #{file}"
    export_data(content)
end

def print_export(dir, last_mark)
    date = convert_dir_to_date(dir)
    mark = convert_dir_to_mark(dir)

    puts 'commit refs/heads/master'
    puts "mark :#{mark}"
    puts "committer #{$author} #{date} -0700"
    export_data("imported from #{dir}")
    puts "from :#{last_mark}" if last_mark

    puts 'deleteall'
    Dir.glob("**/*").each do |file|
        next if !File.file?(file)
        inline_data(file)
    end
    mark
end


# Loop through the directories
last_mark = nil
Dir.chdir(ARGV[0]) do
    Dir.glob("*").each do |dir|
        next if File.file?(dir)

        # move into the target directory
        Dir.chdir(dir) do
            last_mark = print_export(dir, last_mark)
        end
    end
end

If you run this script, you’ll get content that looks something like this:

$ ruby import.rb /opt/import_from
commit refs/heads/master
mark :1
committer John Doe <[email protected]> 1388649600 -0700
data 29
imported from back_2014_01_02deleteall
M 644 inline README.md
data 28
# Hello

This is my readme.
commit refs/heads/master
mark :2
committer John Doe <[email protected]> 1388822400 -0700
data 29
imported from back_2014_01_04from :1
deleteall
M 644 inline main.rb
data 34
#!/bin/env ruby

puts "Hey there"
M 644 inline README.md
(...)

Para ejecutar el importador, se debe pasar esta señal a través de git fast-import mientras que en el directorio Git se desea copiar. Puede crear un nuevo directorio y luego ejecutar git init en él para un punto de partida, y luego ejecutar su script:

$ git init
Initialized empty Git repository in /opt/import_to/.git/
$ ruby import.rb /opt/import_from | git fast-import
git-fast-import statistics:
---------------------------------------------------------------------
Alloc'd objects:       5000
Total objects:           13 (         6 duplicates                  )
      blobs  :            5 (         4 duplicates          3 deltas of          5 attempts)
      trees  :            4 (         1 duplicates          0 deltas of          4 attempts)
      commits:            4 (         1 duplicates          0 deltas of          0 attempts)
      tags   :            0 (         0 duplicates          0 deltas of          0 attempts)
Total branches:           1 (         1 loads     )
      marks:           1024 (         5 unique    )
      atoms:              2
Memory total:          2344 KiB
       pools:          2110 KiB
     objects:           234 KiB
---------------------------------------------------------------------
pack_report: getpagesize()            =       4096
pack_report: core.packedGitWindowSize = 1073741824
pack_report: core.packedGitLimit      = 8589934592
pack_report: pack_used_ctr            =         10
pack_report: pack_mmap_calls          =          5
pack_report: pack_open_windows        =          2 /          2
pack_report: pack_mapped              =       1457 /       1457
---------------------------------------------------------------------

Como puedes ver, cuando se completa con éxito, te da un conjunto de estadísticas sobre lo que logró. En este caso, ha importado un total de 13 objetos para 4 confirmaciones en 1 rama. Ahora, puedes ejecutar git log para ver tu nueva historial:

$ git log -2
commit 3caa046d4aac682a55867132ccdfbe0d3fdee498
Author: John Doe <[email protected]>
Date:   Tue Jul 29 19:39:04 2014 -0700

    imported from current

commit 4afc2b945d0d3c8cd00556fbe2e8224569dc9def
Author: John Doe <[email protected]>
Date:   Mon Feb 3 01:00:00 2014 -0700

    imported from back_2014_02_03

Ahí tienes, un buen y limpio depósito de Git. Es importante tener en cuenta que nada está comprobado - no tiene archivos en su directorio de trabajo al principio. Para obtenerlos, debe reajustar su rama a donde "maestro" está ahora:

$ ls
$ git reset --hard master
HEAD is now at 3caa046 imported from current
$ ls
README.md main.rb

Puedes hacer mucho más con la herramienta "Importación rápida": maneja diferentes modos, datos binarios, múltiples ramas y fusiones, etiquetas, indicadores de progreso y mucho más. Varios ejemplos de escenarios más complejos están disponibles en el directorio `contrib/fast-import' del código fuente Git.