Class: PlexSymlinker::Operation

Inherits:
Object
  • Object
show all
Defined in:
lib/plex_symlinker/operation.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(files_base_dir, symlinks_base_dir, symlink_target_dir: nil) ⇒ Operation

Returns a new instance of Operation.

Examples:

Usage with a custom symlink target dir

# When using a docker container to run this gem, we have to make sure it has access to
# both the files and the directory to place the symlinks in. The easiest way to do so
# is by mounting both directories as volumes.
# The docker image expects the files and symlinks directories to be mounted as  /app/source and /app/target
# respectively:

docker run plex-symlinker -v /path/to/audio/files:/app/source -v /path/to/symlinks:/app/target

# The problem here would be that the generated symlinks would all point to files inside /app/source
# instead of the actual audio file directory as this is the only directly that's known inside the
# docker container.
# To fix this, specifying the actual files directory outside the container as +symlink_target_dir+
# takes precedence when creating the symlinks. This is already done in /bin/plex-symlinker-docker.
# An example initialization for the above paths would therefore be:

Operation.new("/app/source", "/app/target", symlink_target_dir: "/path/to/audio/files")

Parameters:

  • files_base_dir (String)

    The directory the audio files are in. Sub-Directories are scanned accordingly.

  • symlinks_base_dir (String)

    The directory the symlinks and folder structure should be placed in.

  • symlink_target_dir (String) (defaults to: nil)

    In some cases, the created symlinks should not target the actual files directory, but a different one instead. An example would be the usage of this Gem through a Dockerfile with mounted volumes.



33
34
35
36
37
# File 'lib/plex_symlinker/operation.rb', line 33

def initialize(files_base_dir, symlinks_base_dir, symlink_target_dir: nil)
  @files_base_dir = files_base_dir
  @symlinks_base_dir = symlinks_base_dir
  @symlink_target_dir = symlink_target_dir.presence || @files_base_dir
end

Instance Attribute Details

#files_base_dirObject (readonly)

Returns the value of attribute files_base_dir.



3
4
5
# File 'lib/plex_symlinker/operation.rb', line 3

def files_base_dir
  @files_base_dir
end

Returns the value of attribute symlink_target_dir.



3
4
5
# File 'lib/plex_symlinker/operation.rb', line 3

def symlink_target_dir
  @symlink_target_dir
end

Returns the value of attribute symlinks_base_dir.



3
4
5
# File 'lib/plex_symlinker/operation.rb', line 3

def symlinks_base_dir
  @symlinks_base_dir
end

Instance Method Details

#audio_filesObject



53
54
55
# File 'lib/plex_symlinker/operation.rb', line 53

def audio_files
  files(files_base_dir).map(&FileTypes::AudioFile.method(:from_path))
end

#cleanupObject

Removes all symlinks from the target folder that don’t have an existing target any more

TODO: Remove empty directories as well



92
93
94
95
96
97
98
# File 'lib/plex_symlinker/operation.rb', line 92

def cleanup
  PlexSymlinker.logger.info "Removing invalid existing symlinks..."
  symlinks.each do |link|
    current_target = link.target.gsub(symlink_target_dir, files_base_dir)
    File.delete(link.path) unless File.exist?(current_target)
  end
end


66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/plex_symlinker/operation.rb', line 66

def create_symlinks
  PlexSymlinker.logger.info "Creating new symlinks..."

  progress = ProgressBar.create(total: audio_files.size, output: PlexSymlinker.output)

  audio_files.each do |file|
    progress.log " --* #{file.album_artist}/#{file.album}..."

    FileUtils.mkdir_p(File.join(symlinks_base_dir, file.relative_symlink_dir))

    path = file.path.gsub(files_base_dir, symlink_target_dir)
    symlink_path = File.join(symlinks_base_dir, file.relative_symlink_path)

    # If we already have a symlink, don't try to create it again.
    next if File.symlink?(symlink_path)

    File.symlink(path, symlink_path)
    progress.increment
  end
end

#files(dir, extensions = FileTypes::AudioFile.registered_types.keys) ⇒ Array<String>

Searches for files within the given directory and its subdirectories.

Parameters:

  • dir (String)

    The directory to search in

  • extensions (Array<#to_s>) (defaults to: FileTypes::AudioFile.registered_types.keys)

    File extensions to be taken into account. Only files with a matching extension will be returned.

Returns:

  • (Array<String>)

    The paths to all files with matching extensions within the given directory



49
50
51
# File 'lib/plex_symlinker/operation.rb', line 49

def files(dir, extensions = FileTypes::AudioFile.registered_types.keys)
  Dir[File.join(dir, "**/*.{#{extensions.join(",")}}")]
end

#performObject



61
62
63
64
# File 'lib/plex_symlinker/operation.rb', line 61

def perform
  cleanup
  create_symlinks
end


57
58
59
# File 'lib/plex_symlinker/operation.rb', line 57

def symlinks
  files(symlinks_base_dir).map(&Symlink.method(:new))
end