| Class | Repository::SubversionRepository |
| In: |
lib/repo/subversion_repository.rb
|
| Parent: | Repository::AbstractRepository |
Implements AbstractRepository for Subversion repositories It implements the following paradigm:
1. Repositories are created by using SubversionRepository.create()
2. Existing repositories are opened by using either SubversionRepository.open()
or SubversionRepository.new()
| CLOSEABLE_VERSION | = | "1.6.5" |
Semi-private class method: Parses a subversion authz file passed in as a string
# File lib/repo/subversion_repository.rb, line 552
552: def self.__parse_authz_file(authz_string)
553: permissions_mapping = {}
554:
555: permissions_array = authz_string.scan(/\[(.+):\/\]\n([\w\s=]+)/)
556: permissions_array.each do |permissions_group|
557: # The first match is the group repository name
558: user_permissions = {}
559: raw_users_permissions = permissions_group[1].scan(/\s*(\w+)\s*=\s*(\w+)\s*/)
560: raw_users_permissions.each do |raw_user_permissions|
561: user_permissions[raw_user_permissions[0]] = self.__translate_perms_from_file(raw_user_permissions[1])
562: end
563: permissions_mapping[permissions_group[0]] = user_permissions
564: end
565: return permissions_mapping
566: end
Semi-private class method: Transforms passed in permissions into subversion authz file syntax
# File lib/repo/subversion_repository.rb, line 570
570: def self.__prepare_authz_string(permissions)
571: result = ""
572: permissions.each do |repository_name, users_permissions|
573: result += "[#{repository_name}:/]\n"
574: users_permissions.each do |user_id, user_permissions|
575: user_permissions_string = self.__translate_to_svn_perms(user_permissions)
576: result += "#{user_id} = #{user_permissions_string}\n"
577: end
578: result += "\n"
579: end
580: return result
581: end
Semi-private class method: Reads in Repository.conf[:REPOSITORY_PERMISSION_FILE]
# File lib/repo/subversion_repository.rb, line 506
506: def self.__read_in_authz_file()
507: # Check if configuration is in order
508: if Repository.conf[:REPOSITORY_PERMISSION_FILE].nil?
509: raise ConfigurationError.new("Required config 'REPOSITORY_PERMISSION_FILE' not set")
510: end
511: if !File.exist?(Repository.conf[:REPOSITORY_PERMISSION_FILE])
512: File.open(Repository.conf[:REPOSITORY_PERMISSION_FILE], "w").close() # create file if not existent
513: end
514: # Load up the Permissions:
515: file_content = ""
516: File.open(Repository.conf[:REPOSITORY_PERMISSION_FILE], "r+") do |auth_file|
517: auth_file.flock(File::LOCK_EX)
518: file_content = auth_file.read()
519: auth_file.flock(File::LOCK_UN) # release lock
520: end
521: return file_content
522: end
Helper method to translate Subversion permissions to internal permissions
# File lib/repo/subversion_repository.rb, line 682
682: def self.__translate_perms_from_file(perm_string)
683: case (perm_string)
684: when "r"
685: return Repository::Permission::READ
686: when "rw"
687: return Repository::Permission::READ_WRITE
688: else raise "Unknown permissions"
689: end # end case
690: end
Helper method to translate internal permissions to Subversion permissions
# File lib/repo/subversion_repository.rb, line 670
670: def self.__translate_to_svn_perms(permissions)
671: case (permissions)
672: when Repository::Permission::READ
673: return "r"
674: when Repository::Permission::READ_WRITE
675: return "rw"
676: else raise "Unknown permissions"
677: end # end case
678: end
Semi-private class method: Writes out Repository.conf[:REPOSITORY_PERMISSION_FILE]
# File lib/repo/subversion_repository.rb, line 525
525: def self.__write_out_authz_file(authz_file_contents)
526: # Check if configuration is in order
527: if Repository.conf[:IS_REPOSITORY_ADMIN].nil?
528: raise ConfigurationError.new("Required config 'IS_REPOSITORY_ADMIN' not set")
529: end
530: if Repository.conf[:REPOSITORY_PERMISSION_FILE].nil?
531: raise ConfigurationError.new("Required config 'REPOSITORY_PERMISSION_FILE' not set")
532: end
533: # If we're not in authoritative mode, bail out
534: if !Repository.conf[:IS_REPOSITORY_ADMIN] # Are we admin?
535: raise NotAuthorityError.new("Unable to write out repo permissions: Not in authoritative mode!");
536: end
537:
538: if !File.exist?(Repository.conf[:REPOSITORY_PERMISSION_FILE])
539: File.open(Repository.conf[:REPOSITORY_PERMISSION_FILE], "w").close() # create file if not existent
540: end
541: result = false
542: File.open(Repository.conf[:REPOSITORY_PERMISSION_FILE], "w+") do |auth_file|
543: auth_file.flock(File::LOCK_EX)
544: # Blast out the string to the file
545: result = (auth_file.write(authz_file_contents) == authz_file_contents.length)
546: auth_file.flock(File::LOCK_UN) # release lock
547: end
548: return result
549: end
Static method: Yields an existing Subversion repository and closes it afterwards
# File lib/repo/subversion_repository.rb, line 88
88: def self.access(connect_string)
89: repository = self.open(connect_string)
90: yield repository
91: repository.close
92: end
Static method: Returns whether or not the available Svn library supports closing
# File lib/repo/subversion_repository.rb, line 134
134: def self.closeable?
135: return Svn::Client.version.to_s >= CLOSEABLE_VERSION
136: end
Static method: Creates a new Subversion repository at location ‘connect_string‘
# File lib/repo/subversion_repository.rb, line 62
62: def self.create(connect_string)
63: if SubversionRepository.repository_exists?(connect_string)
64: raise RepositoryCollision.new("There is already a repository at #{connect_string}")
65: end
66: if File.exists?(connect_string)
67: raise IOError.new("Could not create a repository at #{connect_string}: some directory with same name exists already")
68: end
69:
70: # create the repository using the ruby bindings
71: fs_config = {Svn::Fs::CONFIG_FS_TYPE => Repository::SVN_FS_TYPES[:fsfs]}
72: repository = Svn::Repos.create(connect_string, {}, fs_config) #raises exception if not successful
73:
74: if SubversionRepository.closeable?
75: repository.close
76: end
77:
78: return true
79: end
Static method: Deletes an existing Subversion repository
# File lib/repo/subversion_repository.rb, line 95
95: def self.delete(repo_path)
96: Svn::Repos::delete(repo_path)
97: end
Deletes permissions over several repositories. Use remove_user to remove permissions of a single repository.
# File lib/repo/subversion_repository.rb, line 460
460: def self.delete_bulk_permissions(repo_names, user_ids)
461: # Check if configuration is in order
462: if Repository.conf[:IS_REPOSITORY_ADMIN].nil?
463: raise ConfigurationError.new("Required config 'IS_REPOSITORY_ADMIN' not set")
464: end
465: # If we're not in authoritative mode, bail out
466: if !Repository.conf[:IS_REPOSITORY_ADMIN] # Are we admin?
467: raise NotAuthorityError.new("Unable to delete bulk permissions: Not in authoritative mode!");
468: end
469:
470: # Read in the authz file
471: authz_file_contents = self.__read_in_authz_file()
472:
473: # Parse the file contents into to something we can work with
474: repo_permissions = self.__parse_authz_file(authz_file_contents)
475:
476: # Delete the user_id for each repository
477: repo_names.each do |repo_name|
478: repo_name = File.basename(repo_name)
479: user_ids.each do |user_id|
480: repo_permissions[repo_name].delete(user_id)
481: end
482: end
483:
484: # Translate the hash into the svn authz file format
485: authz_file_contents = self.__prepare_authz_string(repo_permissions)
486:
487: # Write out the authz file
488: return self.__write_out_authz_file(authz_file_contents)
489: end
Constructor: Connects to an existing Subversion repository, using Ruby bindings; Note: A repository has to be created using SubversionRepository.create(), it it is not yet existent
# File lib/repo/subversion_repository.rb, line 38
38: def initialize(connect_string)
39: # Check if configuration is in order
40: if Repository.conf[:IS_REPOSITORY_ADMIN].nil?
41: raise ConfigurationError.new("Required config 'IS_REPOSITORY_ADMIN' not set")
42: end
43: if Repository.conf[:REPOSITORY_PERMISSION_FILE].nil?
44: raise ConfigurationError.new("Required config 'REPOSITORY_PERMISSION_FILE' not set")
45: end
46: begin
47: super(connect_string) # dummy call to super
48: rescue NotImplementedError; end
49: @repos_path = connect_string
50: @closed = false
51: @repos_auth_file = Repository.conf[:REPOSITORY_PERMISSION_FILE] || File.dirname(connect_string) + "/svn_authz"
52: @repos_admin = Repository.conf[:IS_REPOSITORY_ADMIN]
53: if (SubversionRepository.repository_exists?(@repos_path))
54: @repos = Svn::Repos.open(@repos_path)
55: else
56: raise "Repository does not exist at path \"" + @repos_path + "\""
57: end
58: end
Static method: Opens an existing Subversion repository at location ‘connect_string‘
# File lib/repo/subversion_repository.rb, line 83
83: def self.open(connect_string)
84: return SubversionRepository.new(connect_string)
85: end
Static method: Reports if a Subversion repository exists It‘s in fact a pretty hacky method checking for files typical for Subversion repositories
# File lib/repo/subversion_repository.rb, line 158
158: def self.repository_exists?(repos_path)
159: repos_meta_files_exist = false
160: if File.exist?(File.join(repos_path, "conf"))
161: if File.exist?(File.join(repos_path, "conf/svnserve.conf"))
162: if File.exist?(File.join(repos_path, "format"))
163: repos_meta_files_exist = true
164: end
165: end
166: end
167: return repos_meta_files_exist
168: end
Sets permissions over several repositories. Use set_permissions to set permissions on a single repository.
# File lib/repo/subversion_repository.rb, line 425
425: def self.set_bulk_permissions(repo_names, user_id_permissions_map)
426: # Check if configuration is in order
427: if Repository.conf[:IS_REPOSITORY_ADMIN].nil?
428: raise ConfigurationError.new("Required config 'IS_REPOSITORY_ADMIN' not set")
429: end
430: # If we're not in authoritative mode, bail out
431: if !Repository.conf[:IS_REPOSITORY_ADMIN] # Are we admin?
432: raise NotAuthorityError.new("Unable to set bulk permissions: Not in authoritative mode!");
433: end
434:
435: # Read in the authz file
436: authz_file_contents = self.__read_in_authz_file()
437:
438: # Parse the file contents into to something we can work with
439: repo_permissions = self.__parse_authz_file(authz_file_contents)
440: # Set / clobber permissions on each group for this user
441: repo_names.each do |repo_name|
442: repo_name = File.basename(repo_name)
443: user_id_permissions_map.each do |user_id, permissions|
444: if repo_permissions[repo_name].nil?
445: repo_permissions[repo_name] = {}
446: end
447: repo_permissions[repo_name][user_id] = permissions
448: end
449: end
450:
451: # Translate the hash into the svn authz file format
452: authz_file_contents = self.__prepare_authz_string(repo_permissions)
453:
454: # Write out the authz file
455: return self.__write_out_authz_file(authz_file_contents)
456: end
Not (!) part of the AbstractRepository API: Returns
prop
of Subversion repository file
# File lib/repo/subversion_repository.rb, line 625
625: def __get_file_property(prop, path, revision_number)
626: return @repos.fs.root(revision_number).node_prop(path, Repository::SVN_CONSTANTS[prop])
627: end
Not (!) part of the AbstractRepository API: Returns a hash of files/directories part of the requested revision; Don‘t use it directly, use SubversionRevision‘s ‘files_at_path’ instead
# File lib/repo/subversion_repository.rb, line 600
600: def __get_files(path="/", revision_number=nil)
601: begin
602: entries = @repos.fs.root(revision_number).dir_entries(path)
603: rescue Exception
604: raise FileDoesNotExist.new("#{path} does not exist in the repository for revision #{revision_number}")
605: end
606: entries.each do |key, value|
607: entries[key] = (value.kind == 1) ? :file : :directory
608: end
609: return entries
610: end
Not (!) part of the AbstractRepository API: This function is very similar to @repos.fs.history(); however, it‘s been altered a little to return only an array of revision numbers. This function, in contrast to the original, takes multiple paths and returns one large history for all paths given.
# File lib/repo/subversion_repository.rb, line 642
642: def __get_history(paths, starting_revision=nil, ending_revision=nil)
643: # We do the to_i's because we want to leave the value nil if it is.
644: if (starting_revision.to_i < 0)
645: raise "Invalid starting revision " + starting_revision.to_i.to_s + "."
646: end
647: revision_numbers = []
648: paths = [paths].flatten
649: paths.each do |path|
650: hist = []
651: history_function = Proc.new do |path, revision|
652: yield(path, revision) if block_given?
653: hist << revision
654: end
655: begin
656: Svn::Repos.history2(@repos.fs, path, history_function, nil, starting_revision || 0,
657: ending_revision || @repos.fs.youngest_rev, true)
658: rescue Svn::Error::FS_NOT_FOUND => e
659: raise Repository::FileDoesNotExistConflict.new(path)
660: rescue Svn::Error::FS_NO_SUCH_REVISION => e
661: raise "Ending revision " + ending_revision.to_s + " does not exist."
662: end
663: revision_numbers.concat hist
664: end
665: return revision_numbers.sort.uniq
666: end
Not (!) part of the AbstractRepository API: Returns
The last modified date
of a Subversion repository file or directory
# File lib/repo/subversion_repository.rb, line 634
634: def __get_node_last_modified_date(path, revision_number)
635: return @repos.fs.root(revision_number).stat(path).time2
636: end
Not (!) part of the AbstractRepository API: Returns
prop
of Subversion repository
# File lib/repo/subversion_repository.rb, line 616
616: def __get_property(prop, rev=nil)
617: return @repos.prop(Repository::SVN_CONSTANTS[prop] || prop.to_s, rev)
618: end
Not (!) part of the AbstractRepository API: Check if given file or path exists in repository beeing member of the provided revision
# File lib/repo/subversion_repository.rb, line 592
592: def __path_exists?(path, revision=nil)
593: return @repos.fs.root(revision).check_path(path) != 0
594: end
Adds a user with given permissions to the repository
# File lib/repo/subversion_repository.rb, line 274
274: def add_user(user_id, permissions)
275: if @repos_admin # Are we admin?
276: if !File.exist?(@repos_auth_file)
277: File.open(@repos_auth_file, "w").close() # create file if not existent
278: end
279:
280: retval = false
281: repo_permissions = {}
282: File.open(@repos_auth_file, "r+") do |auth_file|
283: auth_file.flock(File::LOCK_EX)
284: # get current permissions from file
285: file_content = auth_file.read()
286: if (file_content.length != 0)
287: repo_permissions = get_repo_permissions_from_file_string(file_content)
288: end
289: if repo_permissions.key?(user_id)
290: raise UserAlreadyExistent.new(user_id + " already existent")
291: end
292: svn_permissions = self.class.__translate_to_svn_perms(permissions)
293: repo_permissions[user_id] = svn_permissions
294: # inject new permissions into file string
295: write_string = inject_permissions(repo_permissions, defined?(file_content)? file_content: "")
296: # rewind, so that mime-type is preserved
297: auth_file.rewind
298: auth_file.truncate(0) # truncate file
299: retval = (auth_file.write(write_string) == write_string.length)
300: auth_file.flock(File::LOCK_UN) # release lock
301: end
302: return retval
303: else
304: raise NotAuthorityError.new("Unable to modify permissions: Not in authoritative mode!")
305: end
306: end
Closes the repository
# File lib/repo/subversion_repository.rb, line 139
139: def close
140: if self.class.closeable?
141: @repos.close
142: end
143: @closed = true
144: end
Returns whether or not repository is closed
# File lib/repo/subversion_repository.rb, line 147
147: def closed?
148: if self.class.closeable?
149: return @repos.closed?
150: end
151: return @closed
152: end
Carries out actions on a Subversion repository stored in ‘transaction’. In case of certain conflicts corresponding Repositor::Conflict(s) are added to the transaction object
# File lib/repo/subversion_repository.rb, line 233
233: def commit(transaction)
234: jobs = transaction.jobs
235: txn = @repos.fs.transaction # transaction date is set implicitly
236: txn.set_prop(Repository::SVN_CONSTANTS[:author], transaction.user_id)
237: jobs.each do |job|
238: case job[:action]
239: when :add_path
240: begin
241: txn = make_directory(txn, job[:path])
242: rescue Repository::Conflict => e
243: transaction.add_conflict(e)
244: end
245: when :add
246: begin
247: txn = add_file(txn, job[:path], job[:file_data], job[:mime_type])
248: rescue Repository::Conflict => e
249: transaction.add_conflict(e)
250: end
251: when :remove
252: begin
253: txn = remove_file(txn, job[:path], job[:expected_revision_number])
254: rescue Repository::Conflict => e
255: transaction.add_conflict(e)
256: end
257: when :replace
258: begin
259: txn = replace_file(txn, job[:path], job[:file_data], job[:mime_type], job[:expected_revision_number])
260: rescue Repository::Conflict => e
261: transaction.add_conflict(e)
262: end
263: end
264: end
265:
266: if transaction.conflicts?
267: return false
268: end
269: txn.commit
270: return true
271: end
Converts a pathname to an absolute pathname
# File lib/repo/subversion_repository.rb, line 492
492: def expand_path(file_name, dir_string = "/")
493: expanded = File.expand_path(file_name, dir_string)
494: if RUBY_PLATFORM =~ /(:?mswin|mingw)/ #only if the platform is Windows
495: expanded = expanded[2..-1]#remove the drive letter
496: end
497: return expanded
498: end
method : Export an existing Subversion repository to a new folder
# File lib/repo/subversion_repository.rb, line 100
100: def export(repo_dest_dir, revision_number=nil)
101: # Modify the path of the repository
102: # If libsvn-ruby raise a segfault, check the first argument of
103: # Svn::Client::export which must be an URI (ex : file:///home/...)
104:
105: repo_path_dir = "file://" + expand_path(@repos_path)
106: ctx = Svn::Client::Context.new
107:
108: # don't fail on non CA signed ssl server
109: ctx.add_ssl_server_trust_file_provider
110: setup_auth_baton(ctx.auth_baton)
111: ctx.add_username_provider
112:
113: # username and password
114: ctx.add_simple_prompt_provider(0) do |cred, realm, username, may_save|
115: cred.username = "markus"
116: cred.password = "markus"
117: cred.may_save = false
118: end
119:
120: # Raise an error if the destination repository already exists
121: if (File.exists?(repo_dest_dir))
122: raise(ExportRepositoryAlreadyExists, "Exported repository already exists")
123: end
124:
125: begin
126: result = ctx.export( repo_path_dir, repo_dest_dir, revision_number, nil)
127: end
128:
129: return result
130: end
Returns a Repository::SubversionRevision instance holding the latest Subversion repository revision number
# File lib/repo/subversion_repository.rb, line 199
199: def get_latest_revision
200: return get_revision(latest_revision_number())
201: end
Gets permissions of a particular user
# File lib/repo/subversion_repository.rb, line 336
336: def get_permissions(user_id)
337: if svn_auth_file_checks() # do basic file checks
338: repo_permissions = {}
339: File.open(@repos_auth_file) do |auth_file|
340:
341: auth_file.flock(File::LOCK_EX)
342: file_content = auth_file.read()
343: if (file_content.length != 0)
344: repo_permissions = get_repo_permissions_from_file_string(file_content)
345: end
346: auth_file.flock(File::LOCK_UN) # release lock
347: end
348: if !repo_permissions.key?(user_id)
349: raise UserNotFound.new(user_id + " not found")
350: end
351: return self.class.__translate_perms_from_file(repo_permissions[user_id])
352: end
353: end
Returns revision_number wrapped as a SubversionRevision instance
# File lib/repo/subversion_repository.rb, line 205
205: def get_revision(revision_number)
206: return Repository::SubversionRevision.new(revision_number, self)
207: end
Returns a SubversionRevision instance representing a revision at a current timestamp
target_timestamp
should be a Ruby Time instance
# File lib/repo/subversion_repository.rb, line 213
213: def get_revision_by_timestamp(target_timestamp)
214: if !target_timestamp.kind_of?(Time)
215: raise "Was expecting a timestamp of type Time"
216: end
217: target_timestamp = target_timestamp.utc
218: return get_revision(get_revision_number_by_timestamp(target_timestamp))
219: end
Returns a Repository::TransAction object, to work with. Do operations, like ‘add’, ‘remove’, etc. on the transaction instead of the repository
# File lib/repo/subversion_repository.rb, line 223
223: def get_transaction(user_id, comment="")
224: if user_id.nil?
225: raise "Expected a user_id (Repository.get_transaction(user_id))"
226: end
227: return Repository::Transaction.new(user_id, comment)
228: end
Gets a list of users with AT LEAST the provided permissions. Returns nil if there aren‘t any.
# File lib/repo/subversion_repository.rb, line 310
310: def get_users(permissions)
311: if svn_auth_file_checks() # do basic file checks
312: repo_permissions = {}
313: File.open(@repos_auth_file) do |auth_file|
314: auth_file.flock(File::LOCK_EX)
315: file_content = auth_file.read()
316: if (file_content.length != 0)
317: repo_permissions = get_repo_permissions_from_file_string(file_content)
318: end
319: auth_file.flock(File::LOCK_UN) # release lock
320: end
321: result_list = []
322: repo_permissions.each do |user, perm|
323: if self.class.__translate_perms_from_file(perm) >= permissions
324: result_list.push(user)
325: end
326: end
327: if !result_list.empty?
328: return result_list
329: else
330: return nil
331: end
332: end
333: end
Delete user from access list
# File lib/repo/subversion_repository.rb, line 391
391: def remove_user(user_id)
392: if @repos_admin # Are we admin?
393: if !File.exist?(@repos_auth_file)
394: File.open(@repos_auth_file, "w").close() # create file if not existent
395: end
396:
397: retval = false
398: File.open(@repos_auth_file, "r+") do |auth_file|
399: auth_file.flock(File::LOCK_EX)
400: # get current permissions from file
401: file_content = auth_file.read()
402: if (file_content.length != 0)
403: repo_permissions = get_repo_permissions_from_file_string(file_content)
404: end
405: if !repo_permissions.key?(user_id)
406: raise UserNotFound.new(user_id + " not found")
407: end
408: repo_permissions.delete(user_id) # delete user_id
409: # inject new permissions into file string
410: write_string = inject_permissions(repo_permissions, defined?(file_content)? file_content: "")
411: # rewind, so that mime-type is preserved
412: auth_file.rewind
413: auth_file.truncate(0) # truncate file
414: retval = (auth_file.write(write_string) == write_string.length)
415: auth_file.flock(File::LOCK_UN) # release lock
416: end
417: return retval
418: else
419: raise NotAuthorityError.new("Unable to modify permissions: Not in authoritative mode!")
420: end
421: end
Set permissions for a given user
# File lib/repo/subversion_repository.rb, line 356
356: def set_permissions(user_id, permissions)
357: if @repos_admin # Are we admin?
358: if !File.exist?(@repos_auth_file)
359: File.open(@repos_auth_file, "w").close() # create file if not existent
360: end
361:
362: retval = false
363: repo_permissions = {}
364: File.open(@repos_auth_file, "r+") do |auth_file|
365: auth_file.flock(File::LOCK_EX)
366: # get current permissions from file
367: file_content = auth_file.read()
368: if (file_content.length != 0)
369: repo_permissions = get_repo_permissions_from_file_string(file_content)
370: end
371: if !repo_permissions.key?(user_id)
372: raise UserNotFound.new(user_id + " not found")
373: end
374: svn_permissions = self.class.__translate_to_svn_perms(permissions)
375: repo_permissions[user_id] = svn_permissions
376: # inject new permissions into file string
377: write_string = inject_permissions(repo_permissions, defined?(file_content)? file_content: "")
378: # rewind, so that mime-type is preserved
379: auth_file.rewind
380: auth_file.truncate(0) # truncate file
381: retval = (auth_file.write(write_string) == write_string.length)
382: auth_file.flock(File::LOCK_UN) # release lock
383: end
384: return retval
385: else
386: raise NotAuthorityError.new("Unable to modify permissions: Not in authoritative mode!")
387: end
388: end
Given a single object, or an array of objects of type RevisionFile, try to find the file in question, and return it as a string
# File lib/repo/subversion_repository.rb, line 173
173: def stringify_files(files)
174: expects_array = files.kind_of? Array
175: if (!expects_array)
176: files = [files]
177: end
178: files.collect! {|file|
179: if (!file.kind_of? Repository::RevisionFile)
180: raise TypeError.new("Expected a Repository::RevisionFile")
181: end
182: begin
183: @repos.fs.root(file.from_revision).file_contents(File.join(file.path, file.name)){|f| f.read}
184: rescue Svn::Error::FS_NOT_FOUND => e
185: raise FileDoesNotExistConflict.new(File.join(file.path, file.name))
186: end
187: }
188: if (!expects_array)
189: return files.first
190: else
191: return files
192: end
193: end