Skip to content

Commit 72ade15

Browse files
committed
Fixed move command not updating the library properly.
1 parent 84378d8 commit 72ade15

File tree

10 files changed

+74
-66
lines changed

10 files changed

+74
-66
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,4 @@ appsettings.*.json
4242

4343
.fake
4444
*.snap
45+
snap.login

snapcraft/snap/snapcraft.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: fbrary
22
base: core20
3-
version: '2.3.0'
3+
version: '2.4.0'
44
summary: Manage your audio book library from the command line.
55
description: |
66
Use this tool to manage your audiobook library from the

src/cli/Arguments.fs

+2-11
Original file line numberDiff line numberDiff line change
@@ -88,15 +88,6 @@ module Arguments =
8888
| DryRun -> "Do not modify files just print the changes."
8989
| NonInteractive -> "Skip all user interaction."
9090

91-
type MoveArgs =
92-
| [<MainCommand; First>] Id of int
93-
| [<CliPrefix(CliPrefix.None); Unique>] Target of string
94-
interface IArgParserTemplate with
95-
member s.Usage =
96-
match s with
97-
| Id _ -> "Id of the audio book to move."
98-
| Target _ -> "Path to move the audiobook to. Follows the syntax of the `mv` command."
99-
10091
type MainArgs =
10192
| [<AltCommandLine("-V")>] Verbose
10293
| [<AltCommandLine("-l"); First; AltCommandLine("--library-file")>] Library of string
@@ -111,7 +102,7 @@ module Arguments =
111102
| [<CliPrefix(CliPrefix.None)>] Files of ParseResults<FilesArgs>
112103
| [<CliPrefix(CliPrefix.None)>] Unmatched of string
113104
| [<CliPrefix(CliPrefix.None)>] Write of ParseResults<WriteArgs>
114-
| [<CliPrefix(CliPrefix.None)>] Move of ParseResults<MoveArgs>
105+
| [<CliPrefix(CliPrefix.None)>] Move of id:int * target:string
115106
| [<CliPrefix(CliPrefix.None)>] Migrate
116107
| [<CliPrefix(CliPrefix.None)>] Details of int list
117108
| [<CliPrefix(CliPrefix.None)>] Id of string
@@ -134,7 +125,7 @@ module Arguments =
134125
| Write _ -> "Write the meta data stored in the library to the actual mp3/ogg files."
135126
| Migrate -> "Migrate an old library file to the current format."
136127
| Details _ -> "List the complete details (including files) for the given audio books."
137-
| 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."
128+
| 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."
138129
| Id _ -> "Retrieve the id for the audio book that contains the given file."
139130
| Version -> "Echo the version of this software."
140131

src/cli/Audiobook.fs

+8
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ module Audiobook =
2222
| MultiFile files -> (files |> List.head) + (sprintf " + %i more" (files.Length - 1))
2323
| SingleFile file -> file
2424

25+
let sourceAsList (s: AudiobookSource) : string list =
26+
match s with
27+
| SingleFile f -> [ f ]
28+
| MultiFile m -> m
29+
30+
let mergeSource (singles: AudiobookSource list) =
31+
singles |> List.collect sourceAsList
32+
2533
type Audiobook = {
2634
Id: int
2735
Source: AudiobookSource

src/cli/Config.fs

+2-11
Original file line numberDiff line numberDiff line change
@@ -192,11 +192,6 @@ module Config =
192192
Id = -1
193193
Target = String.Empty
194194
}
195-
196-
let applyMoveArg (config: MoveConfig) (m: MoveArgs) : MoveConfig =
197-
match m with
198-
| MoveArgs.Id i -> { config with Id = i }
199-
| MoveArgs.Target t -> { config with Target = t }
200195

201196
type IdConfig = {
202197
Target: string
@@ -387,12 +382,8 @@ module Config =
387382
{ config with Command = Migrate }
388383
| MainArgs.Details ids ->
389384
{ config with Command = Details { Ids = ids } }
390-
| MainArgs.Move m ->
391-
let moveConfig = match config.Command with
392-
| Move m -> m
393-
| _ -> emptyMoveConfig
394-
let updatedMoveConfig = m.GetAllResults() |> List.fold applyMoveArg moveConfig
395-
{ config with Command = Move updatedMoveConfig }
385+
| MainArgs.Move (id, target) ->
386+
{ config with Command = Move { Id = id; Target = target } }
396387
| MainArgs.Id target ->
397388
{ config with Command = Id { Target = target } }
398389
| MainArgs.Version ->

src/cli/Fbrary.fsproj

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<Compile Include="Formatter.fs" />
2020
<Compile Include="Arguments.fs" />
2121
<Compile Include="Config.fs" />
22+
<Compile Include="GlobalConfig.fs" />
2223
<Compile Include="Library.fs" />
2324
<Compile Include="TagLib.fs" />
2425
<Compile Include="Program.fs" />

src/cli/GlobalConfig.fs

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
namespace b0wter.Fbrary
2+
3+
open System
4+
5+
module GlobalConfig =
6+
7+
let private directory = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
8+
let private file = "config.json"
9+
let globalConfigPath = IO.Path.combine (directory, file)
10+
11+
type GlobalConfig = {
12+
LibraryFile: string
13+
}
14+
15+
let deserialize (json: string) : GlobalConfig option =
16+
match Microsoft.FSharpLu.Json.Compact.tryDeserialize<GlobalConfig> json with
17+
| Choice1Of2 c -> Some c
18+
| Choice2Of2 _ -> None
19+
20+
let tryLoad () =
21+
let tryRead = IO.readTextFromFile >> function | Ok c -> Some c | Error _ -> None
22+
23+
if IO.File.exists globalConfigPath then
24+
globalConfigPath
25+
|> tryRead
26+
|> Option.bind deserialize
27+
else None
28+

src/cli/IO.fs

+2-25
Original file line numberDiff line numberDiff line change
@@ -106,29 +106,6 @@ module IO =
106106
let isSamePath p1 p2 =
107107
Path.GetFullPath(p1) = Path.GetFullPath(p2)
108108

109-
let move (source: string) (target: string) : Result<unit, string> =
110-
(*
111-
Rules for moving books:
112-
- cannot move to a non-existing folder
113-
- cannot move to an existing file
114-
*)
115-
let validate source target =
116-
if File.Exists(target) then Error "Cannot move to an existing file."
117-
elif not <| Directory.Exists(target) then Error "Cannot move to a non-existing folder."
118-
else Ok ()
119-
120-
try
121-
122-
123-
let mover = match Directory.Exists(source), File.Exists(source) with
124-
| true, true | false, false -> failwith "Could not determine whether the path is a file or a directory."
125-
| true, false -> Directory.Move
126-
| false, true -> File.Move
127-
128-
Error "not implemented"
129-
with
130-
| error -> Error error.Message
131-
132109
let private singleSeparator = Path.PathSeparator |> string
133110
let private doubleSeparator = String(Path.PathSeparator, 2)
134111
/// Removes redundant elements from the path (e.g. `..` and `.`).
@@ -178,10 +155,10 @@ module IO =
178155

179156
if isAbsolutePath then pathRoot + joined
180157
else joined
181-
158+
182159
let simplifyPath (path: string): string =
183160
let simplified = Path.GetFullPath path
184-
if simplified = (Path.DirectorySeparatorChar |> string) then simplified
161+
if simplified = (Path.DirectorySeparatorChar |> string) || simplified = Path.GetPathRoot(path) then simplified
185162
else simplified.TrimEnd(Path.DirectorySeparatorChar)
186163

187164
/// Finds the largest common path across multiple paths.

src/cli/Program.fs

+28-17
Original file line numberDiff line numberDiff line change
@@ -406,47 +406,44 @@ module Program =
406406
}
407407

408408
let move (config: Config.MoveConfig) (library: Library.Library) =
409-
let moveSingleFile source target =
409+
let moveSingleFile source target : Result<Audiobook.AudiobookSource, string> =
410410
result {
411411
let targetFilename =
412412
if target |> IO.File.hasExtension then target
413413
else IO.Path.combine (target, (source |> IO.File.fileName))
414414
let targetFolderName = targetFilename |> IO.Directory.directoryName
415415
do! IO.Directory.create targetFolderName
416416
do! IO.File.move source targetFilename
417+
return Audiobook.AudiobookSource.SingleFile targetFilename
417418
}
418419

419420
/// Moves all source files to the target.
420421
/// Checks whether the target is an existing file. If it is the process is aborted.
421422
/// Makes sure that the target directory exists.
422-
let moveMultipleFiles (sources: string list) target =
423+
let moveMultipleFiles (sources: string list) target : Result<Audiobook.AudiobookSource, string> =
423424
result {
424425
if target |> IO.File.exists then
425426
return! Error "Cannot move an audio book consisting of multiple files to a file location."
426427
else
427428
do printfn "test"
428429
let basePath = IO.findLargestCommonPath sources
429-
return! sources |> List.traverseResultM (fun s ->
430-
result {
431-
// remove the SeparatorChar because it confuses `Path.combine` because it thinks
432-
// relative path is an absolute path otherwise
430+
let! singles = sources |> List.traverseResultM (fun s ->
433431
let relativePath = s.Substring(basePath.Length).TrimStart(IO.Path.DirectorySeparatorChar)
434432
let targetFilename = IO.Path.combine (target, relativePath)
435-
return! moveSingleFile s targetFilename
436-
}) |> Result.map (fun _ -> ())
433+
moveSingleFile s targetFilename)
434+
return Audiobook.mergeSource singles |> Audiobook.AudiobookSource.MultiFile
437435
}
438436

439-
let move (source: Audiobook.AudiobookSource) target =
440-
result {
441-
return! match source with
442-
| Audiobook.AudiobookSource.SingleFile file -> moveSingleFile file target
443-
| Audiobook.AudiobookSource.MultiFile files -> moveMultipleFiles files target
444-
}
437+
let move (source: Audiobook.AudiobookSource) target : Result<Audiobook.AudiobookSource, string> =
438+
match source with
439+
| Audiobook.AudiobookSource.SingleFile file -> moveSingleFile file target
440+
| Audiobook.AudiobookSource.MultiFile files -> moveMultipleFiles files target
445441

446442
result {
447443
let! book = library |> Library.findById config.Id
448-
do! move book.Source config.Target
449-
return ()
444+
let! updatedSource = move book.Source config.Target
445+
let updatedBook = { book with Source = updatedSource }
446+
return! library |> Library.updateBook updatedBook
450447
}
451448

452449
let identify (config: Config.IdConfig) (library: Library.Library) =
@@ -499,8 +496,22 @@ module Program =
499496
return! f library
500497
}
501498

499+
let addConfigEntriesToToCliArguments (argv: string []) =
500+
match GlobalConfig.tryLoad () with
501+
| Some config ->
502+
let containsLibraryArgument =
503+
argv
504+
|> Array.filter (fun a -> a = "-l" || a = "--library-file" || a = "--library")
505+
|> Array.length > 0
506+
if containsLibraryArgument then argv
507+
else Array.append [| "-l"; config.LibraryFile |] argv
508+
| None ->
509+
argv
510+
511+
502512
[<EntryPoint>]
503513
let main argv =
514+
let argv = addConfigEntriesToToCliArguments argv
504515

505516
let r = result {
506517
let parser, results = parseCommandLineArguments argv
@@ -542,7 +553,7 @@ module Program =
542553
| Config.Details detailsConfig ->
543554
return! (runOnExisting (listDetails detailsConfig))
544555
| Config.Move moveConfig ->
545-
return! (runOnExisting (move moveConfig))
556+
return! (runOnExistingAndSave (move moveConfig))
546557
| Config.Id idConfig ->
547558
return! (runOnExisting ((identify idConfig) >> Ok))
548559
| Config.Version ->

src/cli/Version.fs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ module Version =
44

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

0 commit comments

Comments
 (0)