irongit

Configure synchronization of files and directories through a plugin.

initial commit

huncholanehuncholaneauthored
parent 20ee0a6commit f72b0f24a9ce9bb73d6c7720f742f846bacf7fa7Browse files

11 files changed, +154 -73

+46-0lua/syncmap/dir/entry.lua
@@ -0,0 +1,46 @@
1+local log = require("syncmap.log")
2+local simple_cmd = require("syncmap.simple_cmd")
3+local rsync = require("syncmap.rsync")
4+local M = {
5+ opts = require("syncmap.default"),
6+}
7+
8+---@alias File string
9+---@alias Folder string
10+
11+---@alias Filetype "file"|"dir"
12+
13+---@class DirEntry
14+---@field path File|Folder
15+---@field rsync_flags RsyncFlag[]
16+---@field isfile? boolean
17+---@field isdir? boolean
18+DirEntry = {}
19+
20+---@return DirEntry|nil
21+---@param o DirEntry
22+function DirEntry:new(o)
23+ local stat = vim.uv.fs_stat(o.path)
24+ if stat and stat.type == "file" then
25+ o.isfile = true
26+ elseif stat and stat.type == "directory" then
27+ o.isdir = true
28+ else
29+ log.error(string.format("%q is not a valid file or directory", o.path))
30+ return nil
31+ end
32+
33+ setmetatable(o, self)
34+ self.__index = self
35+ return o
36+end
37+
38+---@param src string
39+function DirEntry:rsync_from(src)
40+ local cmd = { "rsync", unpack(self.rsync_flags), src, self.path }
41+end
42+
43+---@param dst string
44+function DirEntry:rsync_to(dst) end
45+
46+return M
+0-0lua/syncmap/dir/init.lua

No content changes (mode or rename only).

+10-0lua/syncmap/dir/map.lua
@@ -0,0 +1,10 @@
1+---@class MapConfig
2+---@field entries Entry[]
3+
4+---@class Map : MapConfig
5+Map = {}
6+
7+---@field o MapConfig
8+function Map:new(o)
9+ o = o or {}
10+end
+1-0lua/syncmap/exact/entry.lua
@@ -0,0 +1 @@
1+---@class ExactEntry
+0-0lua/syncmap/exact/init.lua

No content changes (mode or rename only).

+9-0lua/syncmap/flags.lua
@@ -0,0 +1,9 @@
1+local log = require("syncmap.log")
2+local M = {
3+ opts = require("syncmap.default"),
4+}
5+
6+---@param flags RsyncFlag[]
7+function M.parse() end
8+
9+return M
+36-0lua/syncmap/inotify.lua
@@ -0,0 +1,36 @@
1+local log = require("syncmap.log")
2+local spawn = require("syncmap.spawn")
3+
4+---@param src string
5+---@param dst string
6+---@param debounce integer
7+---@param rsync_flags RsyncFlag[]
8+return function(src, dst, debounce, rsync_flags)
9+ local cmd = "while inotifywait "
10+ local stat = vim.uv.fs_stat(src)
11+ if stat and stat.type == "directory" then
12+ log.debug(string.format("Setting up inotify for a file.\n%s", src))
13+ cmd = cmd .. string.format("-r -e modify,create,delete %q; ", src)
14+ elseif stat and stat.type == "file" then
15+ log.debug(string.format("Setting up inotify for a file.\n%s", src))
16+ cmd = cmd .. string.format("-e modify %q; ", src)
17+ else
18+ log.error(string.format("Could not stat %s", src))
19+ return "NO STAT"
20+ end
21+ cmd = cmd .. string.format("do rsync %s %q %q sleep %d; done", table.concat(rsync_flags, " "), src, dst, debounce)
22+ local cmd_str_for_log = "sh -c '" .. cmd .. "'"
23+
24+ local handle, pid = spawn("sh", {
25+ args = { "-c", cmd },
26+ path = "sh",
27+ callback = function(code, status, _, pid)
28+ log.debug(string.format("%s\n%d completed with %d code and %d status", cmd_str_for_log, pid, code, status))
29+ end,
30+ })
31+ if not handle then
32+ log.error(string.format("Failed to start the following command.\n%s\nErr: %s", cmd_str_for_log, pid))
33+ else
34+ log.debug(string.format("Started the following command with pid %d\n%s", pid, cmd_str_for_log))
35+ end
36+end
+1-44lua/syncmap/rsync.lua
@@ -6,7 +6,7 @@ local M = {
66
77 ---Runs rsync
88 ---@param args RsyncParams
9-function M.run(args)
9+return function(args)
1010 local cmd = { "rsync", unpack(args.flags), args.src, args.dst }
1111 local result = vim.fn.system(cmd)
1212 if vim.v.shell_error ~= 0 then
@@ -22,46 +22,3 @@ function M.run(args)
2222 end
2323 return result
2424 end
25-
26----@param args RsyncParams
27-function M.spawn_watcher(args)
28- if M.opts.reverse_sync_on_startup then
29- M.run({
30- src = args.dst,
31- dst = args.src,
32- reverse_sync_on_spawn = args.reverse_sync_on_spawn,
33- flags = args.flags,
34- })
35- end
36-
37- local cmd = "while inotifywait "
38- local stat = vim.uv.fs_stat(args.src)
39- if stat and stat.type == "directory" then
40- log.debug(string.format("Setting up inotify for a file.\n%s", args.src))
41- cmd = cmd .. string.format("-r -e modify,create,delete %q; ", args.src)
42- elseif stat and stat.type == "file" then
43- log.debug(string.format("Setting up inotify for a file.\n%s", args.src))
44- cmd = cmd .. string.format("-e modify %q; ", args.src)
45- else
46- log.error(string.format("Could not stat %s", args.src))
47- return "NO STAT"
48- end
49- cmd = cmd .. string.format("do rsync %s %q %q; done", table.concat(args.flags, " "), args.src, args.dst)
50- local cmd_str_for_log = "sh -c '" .. cmd .. "'"
51-
52- local handle, pid = simple_cmd.spawn("sh", {
53- args = { "-c", cmd },
54- path = "sh",
55- callback = function(code, status, _, pid)
56- log.debug(string.format("%s\n%d completed with %d code and %d status", cmd_str_for_log, pid, code, status))
57- end,
58- })
59- if not handle then
60- log.error(string.format("Failed to start the following command.\n%s\nErr: %s", cmd_str_for_log, pid))
61- else
62- log.debug(string.format("Started the following command with pid %d\n%s", pid, cmd_str_for_log))
63- end
64- return pid, cmd_str_for_log
65-end
66-
67-return M
+1-29lua/syncmap/simple_cmd.lua → lua/syncmap/spawn.lua
@@ -1,5 +1,3 @@
1-local M = {}
2-
31 ---@alias StdIO integer|uv.uv_stream_t|nil
42
53 ---@alias SpawnCommandCallback fun(code:integer, signal:integer, handle:uv.uv_process_t, pid:integer)
@@ -21,7 +19,7 @@ local M = {}
2119 ---A wrapper for uv.spawn that includes defaults. This makes it easier to spawn commands in the background. Also automatically closes the handle unless close is specified to false.
2220 ---@param path string the exectuable path
2321 ---@param p SpawnCommandParams
24-function M.spawn(path, p)
22+return function(path, p)
2523 local args = p.args
2624 local stdio = p.stdio or { nil, nil, nil }
2725 local cwd = p.cwd or vim.fn.getcwd()
@@ -56,29 +54,3 @@ function M.spawn(path, p)
5654 end)
5755 return handle, pid
5856 end
59-
60----Kills a process and all of its descendents
61----@param pid integer|string
62-function M.kill(pid)
63- vim.fn.system({ "kill", "-TERM", "-" .. tostring(pid) })
64-end
65-
66----Checks if a process is running
67----@param pid string|integer
68-function M.exists(pid)
69- local result = false
70- local done = false
71- M.spawn("ps", {
72- args = { "-s", tostring(pid) },
73- callback = function(code, _, _, _)
74- result = code == 0
75- done = true
76- end,
77- })
78- vim.wait(100, function()
79- return done
80- end, 10)
81- return result
82-end
83-
84-return M
+50-0lua/syncmap/system.lua
@@ -0,0 +1,50 @@
1+local log = require("syncmap.log")
2+local simple_cmd = require("syncmap.simple_cmd")
3+local M = {
4+ opts = require("syncmap.default"),
5+}
6+
7+---@param args RsyncParams
8+function M.rsync(args)
9+ simple_cmd.spawn()
10+ local cmd = { "rsync", unpack(args.flags), args.src, args.dst }
11+ local result = vim.fn.system(cmd)
12+ if vim.v.shell_error ~= 0 then
13+ log.error(
14+ string.format(
15+ "Failed to run the the following rsync command.\n%s\nResult: %s",
16+ table.concat(cmd, " "),
17+ result
18+ )
19+ )
20+ else
21+ log.debug("Successfully ran the following rsync command.\n" .. table.concat(cmd, " "))
22+ end
23+ return result
24+end
25+
26+---Kills a process and all of its descendents
27+---@param pid integer|string
28+function M.kill(pid)
29+ vim.fn.system({ "kill", "-TERM", "-" .. tostring(pid) })
30+end
31+
32+---Checks if a process is running
33+---@param pid string|integer
34+function M.exists(pid)
35+ local result = false
36+ local done = false
37+ M.spawn("ps", {
38+ args = { "-s", tostring(pid) },
39+ callback = function(code, _, _, _)
40+ result = code == 0
41+ done = true
42+ end,
43+ })
44+ vim.wait(100, function()
45+ return done
46+ end, 10)
47+ return result
48+end
49+
50+return M
+0-0lua/syncmap/watch.lua

No content changes (mode or rename only).