Class: Fixi::Command::Bag

Inherits:
Object
  • Object
show all
Defined in:
lib/fixi/command/bag.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.arghelpObject



11
12
13
# File 'lib/fixi/command/bag.rb', line 11

def self.arghelp
  "<input-dir> <output-dir>"
end

.detailsObject



15
16
17
18
# File 'lib/fixi/command/bag.rb', line 15

def self.details
  "Where:\n  input-dir is an indexed directory whose content should be exported.\n" +
    "  output-dir is the base directory of the bag to be created."
end

.synopsisObject



7
8
9
# File 'lib/fixi/command/bag.rb', line 7

def self.synopsis
  "Export files as a new BagIt bag"
end

Instance Method Details

#execute(args) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/fixi/command/bag.rb', line 20

def execute args
  opts = Trollop::options args do
    banner Fixi::Command.banner "bag"
    opt :algorithms, "Checksum algorithm(s) to use for the bag. This is
      a comma-separated list, which may include md5, sha1, sha256, sha384,
      sha512, and must be a subset of the indexed algorithms. If unspecified,
      manifests will be created for all indexed algorithms.".pack,
      :short => 'l', :type => :string
  end

  raise "Must specify input directory." unless args[0] 
  raise "Must specify output directory." unless args[1]
  raise "Output directory already exists." if File.exists?(args[1])

  input_dir = File.expand_path(args[0])
  output_dir = File.expand_path(args[1])

  index = Fixi::Index.new(input_dir)
  Dir.mkdir(output_dir)

  # if algorithms specified, must be a subset of those indexed
  opts[:algorithms] ||= index.algorithms
  set = Set.new(index.algorithms.split(","))
  subset = Set.new(opts[:algorithms].split(","))
  raise "Specified algorithm(s) must be a subset of #{index.algorithms}" unless subset.subset?(set)

  manifiles = {}
  
  begin
    # write bag declaration
    file = File.new(File.join(args[1], "bagit.txt"), "w")
    file.puts("BagIt-Version: 0.97")
    file.puts("Tag-File-Character-Encoding: UTF-8")
    file.close

    # open manifest files for writing
    opts[:algorithms].split(",").each do |alg|
      filename = File.join(args[1], "manifest-#{alg}.txt")
      manifiles[alg] = File.new(filename, "w")
    end

    # copy all files, preserving attributes
    index.each(input_dir) do |hash|
      relpath = hash['relpath']
      abspath = index.rootpath + '/' + relpath
      if index.file_in_scope(relpath) && File.exists?(abspath)
        bagrelpath = "data" + abspath[input_dir.length..-1]
        destpath = args[1] + "/" + bagrelpath
        manifiles.each do |alg, file|
          file.puts("#{hash[alg]} #{bagrelpath}")
        end
        begin
          FileUtils.cp(abspath, destpath, :preserve => true)
        rescue
          FileUtils.mkdir_p(File.dirname(destpath))
          FileUtils.cp(abspath, destpath, :preserve => true)
        end
      end
    end

    data_dir = output_dir + "/data"

    # revisit all dirs under data/, copying orig dir metadata
    Find.find(data_dir) do |dir|
      if File.directory?(dir) && dir != data_dir
        orig_dir = input_dir + dir[data_dir.length..-1]
        Fixi::(dir, File.stat(orig_dir))
      end
    end
  ensure
    manifiles.each_value { |file| file.close }
  end
end