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
Читать дальше