mirror of
https://github.com/derfenix/photocatalog.git
synced 2026-03-12 07:40:29 +03:00
Compare commits
58 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e66070383f | |||
| 438cd3d86f | |||
| 0cf9b85787 | |||
| a56c582068 | |||
| 3be92806b1 | |||
| 65baf34032 | |||
| 986d16addf | |||
| 57eb22615d | |||
| aa6ba0c07c | |||
| f0bef5fa2d | |||
| 065a56e621 | |||
| e71bb647b8 | |||
| 3ab4a04da0 | |||
| ffe9bfe466 | |||
| a1cafdfb8b | |||
| d20a64206d | |||
| 7fd6d66a12 | |||
| ba2f5da3ac | |||
| d8dffed10a | |||
| 8b3e7bf289 | |||
| d5a88cdad6 | |||
| f4f10bb8fa | |||
| a247c7e77a | |||
| a3754d901d | |||
| 471f17e546 | |||
| 4f050bcae7 | |||
| cb6492dfab | |||
| 8e9e075e39 | |||
| 3258452b5b | |||
| cfc318e14b | |||
| a650096ced | |||
| bd32223557 | |||
| 7793eb9dec | |||
| 6724d80c15 | |||
| b32c74d058 | |||
| 4b2d705906 | |||
| 4f19d006d0 | |||
| 08feb65d86 | |||
| 66a198cf91 | |||
| d2db0a66ad | |||
| ae55a0b71a | |||
| 5e383bb8df | |||
| 2526c0f0cb | |||
| 5de7ba17d8 | |||
| 6a7f2d04f0 | |||
| 9b9129d5fc | |||
| d53b050966 | |||
| 80b4942d0e | |||
| d179279d26 | |||
| bce5d42ac1 | |||
| 87e82d13c8 | |||
| 882d596aa7 | |||
| b0cd8bdefa | |||
| a8b2a94b09 | |||
| 83202087a5 | |||
| ee44aaceab | |||
| db015efba6 | |||
| bd3619137f |
26
flake.lock
generated
Normal file
26
flake.lock
generated
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1736061677,
|
||||||
|
"narHash": "sha256-DjkQPnkAfd7eB522PwnkGhOMuT9QVCZspDpJJYyOj60=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "cbd8ec4de4469333c82ff40d057350c30e9f7d36",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"id": "nixpkgs",
|
||||||
|
"ref": "nixos-24.11",
|
||||||
|
"type": "indirect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
129
flake.nix
Normal file
129
flake.nix
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
{
|
||||||
|
description = "Photo/video organization tool";
|
||||||
|
|
||||||
|
inputs.nixpkgs.url = "nixpkgs/nixos-24.11";
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs }:
|
||||||
|
let
|
||||||
|
lastModifiedDate = self.lastModifiedDate or self.lastModified or "19700101";
|
||||||
|
version = "2.0.4";
|
||||||
|
supportedSystems = [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ];
|
||||||
|
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
|
||||||
|
nixpkgsFor = forAllSystems (system: import nixpkgs { inherit system; });
|
||||||
|
in
|
||||||
|
{
|
||||||
|
packages = forAllSystems (system:
|
||||||
|
let
|
||||||
|
pkgs = nixpkgsFor.${system};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
photocatalog = pkgs.buildGoModule {
|
||||||
|
pname = "photocatalog";
|
||||||
|
inherit version;
|
||||||
|
src = ./.;
|
||||||
|
vendorHash = "sha256-dj11SRRoB8ZbkcQs75HPI0DpW4c5jzY0N8MD1wKpw+4=";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
nixosModules.photocatalog = { config, lib, pkgs, ... }:
|
||||||
|
with lib;
|
||||||
|
{
|
||||||
|
options.photocatalog = {
|
||||||
|
enable = lib.mkEnableOption "Enable photocatalog";
|
||||||
|
|
||||||
|
syncs = mkOption {
|
||||||
|
default = {};
|
||||||
|
description = ''
|
||||||
|
Organization paths with its own params.
|
||||||
|
'';
|
||||||
|
example = {
|
||||||
|
|
||||||
|
};
|
||||||
|
type = types.attrsOf (types.submodule ({ name, ... }: {
|
||||||
|
options = {
|
||||||
|
source = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = name;
|
||||||
|
description = ''
|
||||||
|
Source folder path.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
target = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = ''
|
||||||
|
Target folder path.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
overwrite = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Overwrite files, existing in target.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
watch = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
description = ''
|
||||||
|
Watch for new files in source path.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
skipFullSync = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Do not make full sync.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
mode = mkOption {
|
||||||
|
type = types.enum [ "hardlink" "symlink" "move" "copy" ];
|
||||||
|
default = "hardlink";
|
||||||
|
description = ''
|
||||||
|
Organization mode, one of [ hardlink symlink move copy ].
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf config.photocatalog.enable {
|
||||||
|
environment.systemPackages = [ self.packages.${pkgs.system}.photocatalog ];
|
||||||
|
systemd.user.services = lib.mapAttrs' (name: sync: nameValuePair
|
||||||
|
("photocatalog${lib.replaceStrings ["/"] ["-"] sync.source}")
|
||||||
|
{
|
||||||
|
after = [ "local-fs.target" ];
|
||||||
|
path = [
|
||||||
|
self.packages.${pkgs.system}.photocatalog
|
||||||
|
];
|
||||||
|
wantedBy = [
|
||||||
|
"default.target"
|
||||||
|
];
|
||||||
|
preStart = ''
|
||||||
|
mkdir -p ${sync.target}
|
||||||
|
'' + (if !sync.skipFullSync then (''
|
||||||
|
photocatalog -source ${sync.source} -target ${sync.target} -mode ${sync.mode} ${if sync.overwrite then "-overwrite" else ""}
|
||||||
|
'') else null);
|
||||||
|
script = "photocatalog -source ${sync.source} -target ${sync.target} -skip-full-sync -watch -mode ${sync.mode} ${if sync.overwrite then "-overwrite" else ""}";
|
||||||
|
serviceConfig = {
|
||||||
|
Type="simple";
|
||||||
|
Restart="no";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) config.photocatalog.syncs;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
devShells = forAllSystems (system:
|
||||||
|
let
|
||||||
|
pkgs = nixpkgsFor.${system};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
default = pkgs.mkShell {
|
||||||
|
buildInputs = with pkgs; [ go gopls gotools go-tools ];
|
||||||
|
};
|
||||||
|
});
|
||||||
|
defaultPackage = forAllSystems (system: self.packages.${system}.photocatalog);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -19,7 +19,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultDirMode = 0o777
|
defaultDirMode = 0o774
|
||||||
defaultFileMode = 0o644
|
defaultFileMode = 0o644
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -302,9 +302,13 @@ func (o *Organizer) ensureTargetPath(targetPath string) error {
|
|||||||
for _, part := range strings.Split(relPath, string(filepath.Separator)) {
|
for _, part := range strings.Split(relPath, string(filepath.Separator)) {
|
||||||
dir = filepath.Join(dir, part)
|
dir = filepath.Join(dir, part)
|
||||||
|
|
||||||
if err := os.Mkdir(dir, o.dirMode); err != nil && !os.IsExist(err) {
|
if err := os.Mkdir(dir, os.ModePerm); err != nil && !os.IsExist(err) {
|
||||||
return fmt.Errorf("create target directory path at %s: %w", dir, err)
|
return fmt.Errorf("create target directory path at %s: %w", dir, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := os.Chmod(dir, os.ModePerm&o.dirMode); err != nil {
|
||||||
|
return fmt.Errorf("chmod directory %s: %w", dir, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
9
main.go
9
main.go
@@ -35,7 +35,10 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func loadCfg() application.Config {
|
func loadCfg() application.Config {
|
||||||
cfg := application.Config{}
|
cfg := application.Config{
|
||||||
|
DirMode: 0774,
|
||||||
|
FileMode: 0644,
|
||||||
|
}
|
||||||
|
|
||||||
flag.StringVar(&cfg.SourceDir, "source", "", "Source directory")
|
flag.StringVar(&cfg.SourceDir, "source", "", "Source directory")
|
||||||
flag.StringVar(&cfg.TargetDir, "target", "", "Target directory")
|
flag.StringVar(&cfg.TargetDir, "target", "", "Target directory")
|
||||||
@@ -67,6 +70,10 @@ func loadCfg() application.Config {
|
|||||||
})
|
})
|
||||||
|
|
||||||
flag.Func("mode", "Organizing mode", func(s string) error {
|
flag.Func("mode", "Organizing mode", func(s string) error {
|
||||||
|
if s == "" {
|
||||||
|
cfg.Mode = application.ModeHardlink
|
||||||
|
}
|
||||||
|
|
||||||
cfg.Mode = application.Mode(s)
|
cfg.Mode = application.Mode(s)
|
||||||
|
|
||||||
if !slices.Contains(application.SupportedModes, cfg.Mode) {
|
if !slices.Contains(application.SupportedModes, cfg.Mode) {
|
||||||
|
|||||||
Reference in New Issue
Block a user