1 -module (lwes_file_watcher
).
9 % The goal of this modules is to watch directories and files, and alert
10 % interested parties about when things change.
12 % The usage is as follows
14 % 1. get a scan right now
16 % Scan = scan (["/tmp"]),
18 % 2. see what changed from an empty scan
22 % 3. save a scan then see what changed the next time
24 % changes (OldScan, NewScan)
26 % Changes will return a list of the form
28 % [ {dir, added, "dir"},
29 % {dir, removed, "dir"},
30 % {file, added, "file"},
31 % {file, removed, "file"},
32 % {file, changed, "file"}
35 %%====================================================================
37 %%====================================================================
39 scan_filepaths (FilePaths
).
42 file_changes ([], Scan
).
44 changes (OldScan
, NewScan
) ->
45 file_changes (OldScan
, NewScan
).
47 %%====================================================================
49 %%====================================================================
51 ordsets:from_list (lists:flatten (scan_filepaths (L
, []))).
53 scan_filepaths ([First
= [_
|_
]|Rest
], Accum
) ->
54 scan_filepaths (Rest
, [ scan_filepath (First
) | Accum
]);
55 scan_filepaths ([First
], Accum
) ->
56 [ scan_filepath (First
) | Accum
];
57 scan_filepaths (First
, Accum
) ->
58 [ scan_filepath (First
) | Accum
].
60 % non-tail recursively scan directory/file and return whether it is a
61 % file, a directory or missing
64 scan_filepath (FilePath
) ->
65 case filelib:is_dir (FilePath
) of
67 case file:list_dir (FilePath
) of
72 FP
= filename:join ([FilePath
, F
]),
73 [ scan_filepath (FP
) | A
]
83 case filelib:is_regular (FilePath
) of
85 [ { file
, FilePath
, filelib:last_modified (FilePath
) } ];
91 file_changes (OldScan
, NewScan
) ->
92 file_changes (OldScan
, NewScan
, []).
94 file_changes ([], [], Accum
) ->
95 lists:reverse (Accum
);
96 file_changes (OL
= [], [{dir
, D
} | NR
], Accum
) ->
97 file_changes (OL
, NR
, [ {dir
, added
, D
} | Accum
]);
98 file_changes (OL
= [], [{file
, F
, _
} | NR
], Accum
) ->
99 file_changes (OL
, NR
, [ {file
, added
, F
} | Accum
]);
100 file_changes ([{dir
, D
} | OR
], NL
= [], Accum
) ->
101 file_changes (OR
, NL
, [ {dir
, removed
, D
} | Accum
]);
102 file_changes ([{file
, F
, _
} | OR
], NL
= [], Accum
) ->
103 file_changes (OR
, NL
, [ {file
, removed
, F
} | Accum
]);
104 file_changes ([O
|OR
], [N
|NR
], Accum
) when O
=:= N
->
105 file_changes (OR
, NR
, Accum
);
106 file_changes ([{file
, FP
, OLM
}|OR
], [{file
, FP
, NLM
}|NR
], Accum
)
108 file_changes (OR
, NR
, [ {file
, changed
, FP
} | Accum
]);
109 file_changes ([O
= {file
, F
, _
}|OR
], NF
= [N
|_
], Accum
) when O
< N
->
110 file_changes (OR
, NF
, [ {file
, removed
, F
} | Accum
]);
111 file_changes ([O
= {dir
, D
}|OR
], NF
= [N
|_
], Accum
) when O
< N
->
112 file_changes (OR
, NF
, [ {dir
, removed
, D
} | Accum
]);
113 file_changes (OF
= [O
|_
], [N
= {file
, F
, _
}|NR
], Accum
) when O
> N
->
114 file_changes (OF
, NR
, [ {file
, added
, F
} | Accum
]);
115 file_changes (OF
= [O
|_
], [N
= {dir
, D
}|NR
], Accum
) when O
> N
->
116 file_changes (OF
, NR
, [ {dir
, added
, D
} | Accum
]).
118 %%====================================================================
120 %%====================================================================
122 -include_lib ("eunit/include/eunit.hrl").
124 % write tests here :)