Skip to content

Commit

Permalink
Fixed move command not updating the library properly.
Browse files Browse the repository at this point in the history
  • Loading branch information
b0wter committed Apr 28, 2021
1 parent 84378d8 commit 72ade15
Show file tree
Hide file tree
Showing 10 changed files with 74 additions and 66 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,4 @@ appsettings.*.json

.fake
*.snap
snap.login
2 changes: 1 addition & 1 deletion snapcraft/snap/snapcraft.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: fbrary
base: core20
version: '2.3.0'
version: '2.4.0'
summary: Manage your audio book library from the command line.
description: |
Use this tool to manage your audiobook library from the
Expand Down
13 changes: 2 additions & 11 deletions src/cli/Arguments.fs
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,6 @@ module Arguments =
| DryRun -> "Do not modify files just print the changes."
| NonInteractive -> "Skip all user interaction."

type MoveArgs =
| [<MainCommand; First>] Id of int
| [<CliPrefix(CliPrefix.None); Unique>] Target of string
interface IArgParserTemplate with
member s.Usage =
match s with
| Id _ -> "Id of the audio book to move."
| Target _ -> "Path to move the audiobook to. Follows the syntax of the `mv` command."

type MainArgs =
| [<AltCommandLine("-V")>] Verbose
| [<AltCommandLine("-l"); First; AltCommandLine("--library-file")>] Library of string
Expand All @@ -111,7 +102,7 @@ module Arguments =
| [<CliPrefix(CliPrefix.None)>] Files of ParseResults<FilesArgs>
| [<CliPrefix(CliPrefix.None)>] Unmatched of string
| [<CliPrefix(CliPrefix.None)>] Write of ParseResults<WriteArgs>
| [<CliPrefix(CliPrefix.None)>] Move of ParseResults<MoveArgs>
| [<CliPrefix(CliPrefix.None)>] Move of id:int * target:string
| [<CliPrefix(CliPrefix.None)>] Migrate
| [<CliPrefix(CliPrefix.None)>] Details of int list
| [<CliPrefix(CliPrefix.None)>] Id of string
Expand All @@ -134,7 +125,7 @@ module Arguments =
| Write _ -> "Write the meta data stored in the library to the actual mp3/ogg files."
| Migrate -> "Migrate an old library file to the current format."
| Details _ -> "List the complete details (including files) for the given audio books."
| Move _ -> "Move the audio book to a new folder. You can specify the book by id or path. For books with multiple files you need to supply the book's root folder."
| Move _ -> "Move the audio book to a new folder. You specify the book by id followed by the target path. For books with multiple files you need to supply the book's root folder."
| Id _ -> "Retrieve the id for the audio book that contains the given file."
| Version -> "Echo the version of this software."

8 changes: 8 additions & 0 deletions src/cli/Audiobook.fs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ module Audiobook =
| MultiFile files -> (files |> List.head) + (sprintf " + %i more" (files.Length - 1))
| SingleFile file -> file

let sourceAsList (s: AudiobookSource) : string list =
match s with
| SingleFile f -> [ f ]
| MultiFile m -> m

let mergeSource (singles: AudiobookSource list) =
singles |> List.collect sourceAsList

type Audiobook = {
Id: int
Source: AudiobookSource
Expand Down
13 changes: 2 additions & 11 deletions src/cli/Config.fs
Original file line number Diff line number Diff line change
Expand Up @@ -192,11 +192,6 @@ module Config =
Id = -1
Target = String.Empty
}

let applyMoveArg (config: MoveConfig) (m: MoveArgs) : MoveConfig =
match m with
| MoveArgs.Id i -> { config with Id = i }
| MoveArgs.Target t -> { config with Target = t }

type IdConfig = {
Target: string
Expand Down Expand Up @@ -387,12 +382,8 @@ module Config =
{ config with Command = Migrate }
| MainArgs.Details ids ->
{ config with Command = Details { Ids = ids } }
| MainArgs.Move m ->
let moveConfig = match config.Command with
| Move m -> m
| _ -> emptyMoveConfig
let updatedMoveConfig = m.GetAllResults() |> List.fold applyMoveArg moveConfig
{ config with Command = Move updatedMoveConfig }
| MainArgs.Move (id, target) ->
{ config with Command = Move { Id = id; Target = target } }
| MainArgs.Id target ->
{ config with Command = Id { Target = target } }
| MainArgs.Version ->
Expand Down
1 change: 1 addition & 0 deletions src/cli/Fbrary.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<Compile Include="Formatter.fs" />
<Compile Include="Arguments.fs" />
<Compile Include="Config.fs" />
<Compile Include="GlobalConfig.fs" />
<Compile Include="Library.fs" />
<Compile Include="TagLib.fs" />
<Compile Include="Program.fs" />
Expand Down
28 changes: 28 additions & 0 deletions src/cli/GlobalConfig.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
namespace b0wter.Fbrary

open System

module GlobalConfig =

let private directory = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
let private file = "config.json"
let globalConfigPath = IO.Path.combine (directory, file)

type GlobalConfig = {
LibraryFile: string
}

let deserialize (json: string) : GlobalConfig option =
match Microsoft.FSharpLu.Json.Compact.tryDeserialize<GlobalConfig> json with
| Choice1Of2 c -> Some c
| Choice2Of2 _ -> None

let tryLoad () =
let tryRead = IO.readTextFromFile >> function | Ok c -> Some c | Error _ -> None

if IO.File.exists globalConfigPath then
globalConfigPath
|> tryRead
|> Option.bind deserialize
else None

27 changes: 2 additions & 25 deletions src/cli/IO.fs
Original file line number Diff line number Diff line change
Expand Up @@ -106,29 +106,6 @@ module IO =
let isSamePath p1 p2 =
Path.GetFullPath(p1) = Path.GetFullPath(p2)

let move (source: string) (target: string) : Result<unit, string> =
(*
Rules for moving books:
- cannot move to a non-existing folder
- cannot move to an existing file
*)
let validate source target =
if File.Exists(target) then Error "Cannot move to an existing file."
elif not <| Directory.Exists(target) then Error "Cannot move to a non-existing folder."
else Ok ()

try


let mover = match Directory.Exists(source), File.Exists(source) with
| true, true | false, false -> failwith "Could not determine whether the path is a file or a directory."
| true, false -> Directory.Move
| false, true -> File.Move

Error "not implemented"
with
| error -> Error error.Message

let private singleSeparator = Path.PathSeparator |> string
let private doubleSeparator = String(Path.PathSeparator, 2)
/// Removes redundant elements from the path (e.g. `..` and `.`).
Expand Down Expand Up @@ -178,10 +155,10 @@ module IO =

if isAbsolutePath then pathRoot + joined
else joined

let simplifyPath (path: string): string =
let simplified = Path.GetFullPath path
if simplified = (Path.DirectorySeparatorChar |> string) then simplified
if simplified = (Path.DirectorySeparatorChar |> string) || simplified = Path.GetPathRoot(path) then simplified
else simplified.TrimEnd(Path.DirectorySeparatorChar)

/// Finds the largest common path across multiple paths.
Expand Down
45 changes: 28 additions & 17 deletions src/cli/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -406,47 +406,44 @@ module Program =
}

let move (config: Config.MoveConfig) (library: Library.Library) =
let moveSingleFile source target =
let moveSingleFile source target : Result<Audiobook.AudiobookSource, string> =
result {
let targetFilename =
if target |> IO.File.hasExtension then target
else IO.Path.combine (target, (source |> IO.File.fileName))
let targetFolderName = targetFilename |> IO.Directory.directoryName
do! IO.Directory.create targetFolderName
do! IO.File.move source targetFilename
return Audiobook.AudiobookSource.SingleFile targetFilename
}

/// Moves all source files to the target.
/// Checks whether the target is an existing file. If it is the process is aborted.
/// Makes sure that the target directory exists.
let moveMultipleFiles (sources: string list) target =
let moveMultipleFiles (sources: string list) target : Result<Audiobook.AudiobookSource, string> =
result {
if target |> IO.File.exists then
return! Error "Cannot move an audio book consisting of multiple files to a file location."
else
do printfn "test"
let basePath = IO.findLargestCommonPath sources
return! sources |> List.traverseResultM (fun s ->
result {
// remove the SeparatorChar because it confuses `Path.combine` because it thinks
// relative path is an absolute path otherwise
let! singles = sources |> List.traverseResultM (fun s ->
let relativePath = s.Substring(basePath.Length).TrimStart(IO.Path.DirectorySeparatorChar)
let targetFilename = IO.Path.combine (target, relativePath)
return! moveSingleFile s targetFilename
}) |> Result.map (fun _ -> ())
moveSingleFile s targetFilename)
return Audiobook.mergeSource singles |> Audiobook.AudiobookSource.MultiFile
}

let move (source: Audiobook.AudiobookSource) target =
result {
return! match source with
| Audiobook.AudiobookSource.SingleFile file -> moveSingleFile file target
| Audiobook.AudiobookSource.MultiFile files -> moveMultipleFiles files target
}
let move (source: Audiobook.AudiobookSource) target : Result<Audiobook.AudiobookSource, string> =
match source with
| Audiobook.AudiobookSource.SingleFile file -> moveSingleFile file target
| Audiobook.AudiobookSource.MultiFile files -> moveMultipleFiles files target

result {
let! book = library |> Library.findById config.Id
do! move book.Source config.Target
return ()
let! updatedSource = move book.Source config.Target
let updatedBook = { book with Source = updatedSource }
return! library |> Library.updateBook updatedBook
}

let identify (config: Config.IdConfig) (library: Library.Library) =
Expand Down Expand Up @@ -499,8 +496,22 @@ module Program =
return! f library
}

let addConfigEntriesToToCliArguments (argv: string []) =
match GlobalConfig.tryLoad () with
| Some config ->
let containsLibraryArgument =
argv
|> Array.filter (fun a -> a = "-l" || a = "--library-file" || a = "--library")
|> Array.length > 0
if containsLibraryArgument then argv
else Array.append [| "-l"; config.LibraryFile |] argv
| None ->
argv


[<EntryPoint>]
let main argv =
let argv = addConfigEntriesToToCliArguments argv

let r = result {
let parser, results = parseCommandLineArguments argv
Expand Down Expand Up @@ -542,7 +553,7 @@ module Program =
| Config.Details detailsConfig ->
return! (runOnExisting (listDetails detailsConfig))
| Config.Move moveConfig ->
return! (runOnExisting (move moveConfig))
return! (runOnExistingAndSave (move moveConfig))
| Config.Id idConfig ->
return! (runOnExisting ((identify idConfig) >> Ok))
| Config.Version ->
Expand Down
2 changes: 1 addition & 1 deletion src/cli/Version.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ module Version =

// This version is updated automatically by the `publish` command.
// The script only works if the version number consists of three numbers separated by dots.
let current = "2.1"
let current = "2.3.0"

0 comments on commit 72ade15

Please sign in to comment.