Module: Amp::Repositories::Stores

Extended by:
Stores
Included in:
Stores
Defined in:
lib/amp/repository/store.rb

Defined Under Namespace

Modules: FilenameCache Classes: BasicStore, EncodedOpener, EncodedStore, FilenameCacheStore, StoreError

Constant Summary collapse

WINDOWS_RESERVED_FILENAMES =

can’t name a file one of these on windows, apparently

%w(con prn aux nul com1
com2 com3 com4 com5 com6 com7 com8 com8 lpt1 lpt2
lpt3 lpt4 lpt5 lpt6 lpt7 lpt8 lpt9)
MAX_PATH_LEN_IN_HGSTORE =
120
DIR_PREFIX_LEN =
8
MAX_SHORTENED_DIRS_LEN =
8 * (DIR_PREFIX_LEN + 1) - 4

Instance Method Summary collapse

Instance Method Details

#auxilliary_encode(path) ⇒ Object

Copypasta



413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
# File 'lib/amp/repository/store.rb', line 413

def auxilliary_encode(path)
  res = []
  path.split('/').each do |n|
    if n.any?
      base = n.split('.')[0]
      if !(base.nil?) && base.any? && WINDOWS_RESERVED_FILENAMES.include?(base)
        ec = "~%02x" % n[2,1].ord
        n = n[0..1] + ec + n[3..-1]
      end
      if ['.',' '].include? n[-1,1]
        n = n[0..-2] + ("~%02x" % n[-1,1].ord)
      end
    end
    res << n
  end
  res.join("/")
end

#decode_filename(s) ⇒ Object

Decodes an encoding performed by encode_filename

Parameters:

  • s (String)

    an encoded file path

  • the (String)

    decoded file path



385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
# File 'lib/amp/repository/store.rb', line 385

def decode_filename(s)
  cmap = illegal_character_map true
  dmap = {}
  cmap.each do |k, v|
    dmap[v] = k
  end
  
  i = 0
  result = []
  while i < s.size
    1.upto(3) do |l|
      if dmap[s[i..(i+l-1)]]
        result << dmap[s[i..(i+l-1)]]
        i += l
        break
      end
    end
  end
  result.join
end

#encode_filename(s, underscore = true) ⇒ String

Reversible encoding of the filename

Parameters:

  • s (String)

    a file’s path you wish to encode

  • underscore (Boolean) (defaults to: true)

    should we insert underscores when downcasing letters? (e.g. if true, “A” => “_a”)

Returns:

  • (String)

    an encoded file path



375
376
377
378
# File 'lib/amp/repository/store.rb', line 375

def encode_filename(s, underscore=true)
  cmap = illegal_character_map underscore
  s.split("").map {|c| cmap[c]}.join
end

#hybrid_encode(path) ⇒ String

uber encoding that’s straight up crazy. Max length of 120 means we have a non-reversible encoding, but since the FilenameCache only cares about name lookups, one-way is really all that matters!

Parameters:

  • path (String)

    the path to encode

Returns:

  • (String)

    an encoded path, with a maximum length of 120.



449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
# File 'lib/amp/repository/store.rb', line 449

def hybrid_encode(path)
  return path unless path =~ /data\//
  ndpath = path["data/".size..-1]
  res = "data/" + auxilliary_encode(encode_filename(ndpath))
  if res.size > MAX_PATH_LEN_IN_HGSTORE
    digest = path.sha1.hexdigest
    aep = auxilliary_encode(lower_encode(ndpath))
    root, ext = File.amp_split_extension aep
    parts = aep.split('/')
    basename = File.basename aep
    sdirs = []
    parts[0..-2].each do |p|
      d = p[0..(DIR_PREFIX_LEN-1)]
      
      d = d[0..-2] + "_" if " .".include?(d[-1,1])
      
      t = sdirs.join("/") + "/" + d
      break if t.size > MAX_SHORTENED_DIRS_LEN
    
      sdirs << d
    end
    dirs = sdirs.join("/")
    dirs += "/" if dirs.size > 0
    
    res = "dh/" + dirs + digest + ext
    space_left = MAX_PATH_LEN_IN_HGSTORE - res.size
    if space_left > 0
      filler = basename[0..(space_left-1)]
      res = "dh/" + dirs + filler + digest + ext
    end
  end
  return res
      
end

#illegal_character_map(underscore = true) ⇒ Object

Gets the basic character map that maps disallowed letters to allowable substitutes.

Parameters:

  • underscore (Boolean) (defaults to: true)

    Should underscores be inserted in front of capital letters before we downcase them? (e.g. if true, “A” => “_a”)



353
354
355
356
357
358
359
360
361
362
363
364
365
# File 'lib/amp/repository/store.rb', line 353

def illegal_character_map(underscore=true)
  e = '_'
  win_reserved = "\\:*?\"<>|".split("").map {|x| x.ord}
  cmap = {}; 0.upto(126) {|x| cmap[x.chr] = x.chr}
  ((0..31).to_a + (126..255).to_a + win_reserved).each do |x|
    cmap[x.chr] = "~%02x" % x
  end
  ((("A".ord)..("Z".ord)).to_a + [e.ord]).each do |x|
    cmap[x.chr] = e + x.chr.downcase if underscore
    cmap[x.chr] = x.chr.downcase     unless underscore
  end
  cmap
end

#lower_encode(s) ⇒ Object

Normal encoding, but without extra underscores in the filenames.



433
434
435
# File 'lib/amp/repository/store.rb', line 433

def lower_encode(s)
  encode_filename s, false
end

#pick(requirements, path, opener, pathjoiner = nil) ⇒ Object

Picks which store to use, given a list of requirements.



7
8
9
10
11
12
13
14
15
16
17
18
# File 'lib/amp/repository/store.rb', line 7

def pick(requirements, path, opener, pathjoiner=nil)
  pathjoiner ||= proc {|*args| File.join(args) }
  if requirements.include? 'store'
    if requirements.include? 'fncache'
      return FilenameCacheStore.new(path, opener, pathjoiner)
    else
      return EncodedStore.new(path, EncodedOpener, pathjoiner)
    end
  else
    return BasicStore.new(path, opener, pathjoiner)
  end
end