Скотт Чакон - Pro Git
- Название:Pro Git
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Скотт Чакон - Pro Git краткое содержание
В книге рассматриваются следующие темы: основы Git;
ветвление в Git;
Git на сервере;
распределённый Git;
GitHub;
инструменты Git;
настройка Git;
Git и другие системы контроля версий.
Pro Git - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
end
end
end
Вы выполняете функцию print_export внутри каждой директории. Она принимает на вход текущую директорию и результат предыдущего вызова и помечает текущую директорию, возвращая данные для последующих вызовов; таким образом связывая коммиты. Пометки используются для связи коммитов вместе. Итак, первым делом нужно сгенерировать метку по директории:
mark = convert_dir_to_mark(dir)
Создадим массив директорий и используем индекс директории в нём как метку; это удобно, ведь метка должна быть целым числом. Мы написали такой код:
$marks = []
defconvert_dir_to_mark(dir)
if!$marks.include?(dir)
$marks << dir
end
($marks.index(dir) + 1).to_s
end
Теперь, когда у нас есть целочисленная метка для коммита, нужна дата. У нас она хранится в имени директории, придётся достать её оттуда. Следующая строка в print_export:
date = convert_dir_to_date(dir)
where convert_dir_to_date is defined as
defconvert_dir_to_date(dir)
ifdir == 'current'
returnTime.now().to_i
else
dir = dir.gsub( 'back_' , '' )
(year, month, day) = dir.split( '_' )
returnTime.local(year, month, day).to_i
end
end
Этот код вернёт целочисленное представление даты для каждой директории. И последний кусочек мозаики: автор изменений. Это значение жёстко задано в глобальной переменной:
$author = 'John Doe '
Теперь всё готово для вывода нужной fast-import'у информации. Нужно указать, что создаётся коммит на определённой ветке, затем вывести сгенерированную метку, автора и время изменений и ссылку на предыдущий коммит, если такой имеется. Код выглядит следующим образом:
# 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 iflast_mark
Для простоты, мы определили часовой пояс как -0700 прямо в выходной строке. Часовой пояс задаётся как смещение от UTC. Сообщение коммита задаётся следующим образом:
data (size)\n(contents)
Первым идёт слово data, затем длина сообщения, новая строка и, наконец, само сообщение. Похожим образом задаётся и содержимое коммитов, поэтому создадим метод-помощник:
defexport_data(string)
print "data #{ string.size }\n#{ string }"
end
Осталось лишь задать содержимое каждого коммита. Это довольно просто, потому что все данные хранятся в отдельных директориях — достаточно напечатать команду deleteall и содержимое всех файлов в директории. После этого Git запишет слепки:
puts 'deleteall'
Dir.glob( "**/*" ).each do|file|
next if!File.file?(file)
inline_data(file)
end
Замечание: многие системы работают с дельтами (разницами от одного состояния к последующему); fast-import имеет команды для задания изменений: какие файлы были добавлены, удалены или изменены. Вы можете вычислять разницу между состояниями и передавать её в fast-import, но это довольно сложно, гораздо проще передавать Git все данные. За полным описанием принимаемых форматов обратитесь к руководству fast-import.
Формат для указания нового содержимого или изменений следующий:
M 644 inline path/to/file
data (size)
(file contents)
Здесь 644 — это права доступа к файлу. Если файл должен быть исполняемым, вам нужно определить это и передать 755. Слово inline говорит о том, что вы выведете содержимое файла после этой строки. Таким образом, метод inline_data может выглядеть так:
definline_data(file, code = 'M' , mode = '644' )
content = File.read(file)
puts " #{ code } #{ mode }inline #{ file }"
export_data(content)
end
Мы используем определённый ранее метод export_data потому что форматы содержимого коммитов и их сообщений одинаковы.
И последнее что нужно сделать — это вернуть метку для последующих вызовов:
returnmark
Если вы используете ОС Windows есть ещё кое-что. Как мы упоминали ранее, Windows использует CRLF для новых строк, в то время как git fast-import ожидает только LF. Чтобы исправить этот недостаток Windows и осчастливить git fast-import, просто прикажите Ruby использовать LF вместо CRLF:
$stdout.binmode
Вот и всё. Ниже приведён весь скрипт целиком:
#!/usr/bin/env ruby
$stdout.binmode
$author = "John Doe "
$marks = []
defconvert_dir_to_mark(dir)
if!$marks.include?(dir)
$marks << dir
end
($marks.index(dir)+1).to_s
end
defconvert_dir_to_date(dir)
ifdir == 'current'
returnTime.now().to_i
else
dir = dir.gsub( 'back_' , '' )
(year, month, day) = dir.split( '_' )
returnTime.local(year, month, day).to_i
end
end
defexport_data(string)
print "data #{ string.size }\n#{ string }"
end
definline_data(file, code= 'M' , mode= '644' )
content = File.read(file)
puts " #{ code } #{ mode }inline #{ file }"
export_data(content)
end
defprint_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 }" iflast_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 ifFile.file?(dir)
# move into the target directory
Dir.chdir(dir) do
last_mark = print_export(dir, last_mark)
end
end
end
Если вы выполните этот скрипт, он выведет примерно следующее:
$ruby import.rb /opt/import_from
commit refs/heads/master
mark :1
committer John Doe 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 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
(...)
Чтобы импортировать репозиторий перенаправьте этот вывод в команду git fast-import, запущенную в директории с целевым Git-репозиторием. Вы можете создать новую директорию, выполнить в ней git init, а затем запустить свой скрипт:
$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
Читать дальшеИнтервал:
Закладка: