1 module unde.file_manager.move_paths;
2 
3 import unde.global_state;
4 import unde.lsblk;
5 import unde.lib;
6 import unde.scan;
7 import unde.path_mnt;
8 
9 import std.stdio;
10 import std.conv;
11 import core.stdc.stdlib;
12 import std.math;
13 import berkeleydb.all;
14 import std.stdint;
15 import core.stdc.stdlib;
16 import std..string;
17 import std.algorithm.sorting;
18 import std.utf;
19 import std.process;
20 import std.concurrency;
21 import core.time;
22 import core.thread;
23 import std.datetime;
24 import std.regex;
25 import std.algorithm.sorting;
26 
27 import unde.file_manager.copy_paths;
28 import unde.file_manager.remove_paths;
29 import unde.slash;
30 
31 import derelict.sdl2.sdl;
32 import derelict.sdl2.ttf;
33 import derelict.sdl2.image;
34 
35 import std.file;
36 
37 immutable DRect drect_zero = DRect(0, 0, 0, 0);
38 
39 private long
40 move_path(FMGlobalState mgs, PathMnt path, string move_to, bool remove_flag, Tid tid)
41 {
42     string orig_move_to = move_to;
43     string dir_to = move_to;
44 
45     if (move_to[$-1] == SL[0])
46     {
47         string name = path.path[path.path.lastIndexOf(SL)+1..$];
48         move_to ~= name;
49     }
50     else
51         dir_to = getParent(dir_to);
52 
53     try
54     {
55         auto de1 = DirEntry(path._next);
56         auto de2 = DirEntry(dir_to);
57 
58 	
59 	version(Posix)
60 	{
61         bool the_same_filesystem = de1.statBuf.st_dev == de2.statBuf.st_dev;
62 	}
63 	else version(Windows)
64 	{
65 	bool the_same_filesystem = path._next[0] == dir_to[0];
66 	}
67 	if ( the_same_filesystem )
68         {
69             if (path._next[$-1] == SL[0]) path._next = path._next[0..$-1];
70             /*writefln("move.thread send to %s (%s, %s, %s, %s)", 
71                     tid, thisTid, path._next, move_to, "send");*/
72             send(tid, thisTid, path._next, move_to, true, MsgState.Send);
73             MsgState resent;
74             do
75             {
76                 //writefln("move.thread %s wait for resent", thisTid);
77                 receive( (MsgState msg) { 
78                         resent = msg; 
79                         /*writefln("move.thread %s receive %s", thisTid, msg);*/ } );
80             } while (resent != MsgState.Resent);
81 
82             rename(path.path, move_to);
83 
84             bool size_updated = false;
85             /* It is good to do, but there is no src path to copy info from it
86             while (!size_updated)
87             {
88                 size_updated = update_progress(mgs, path, move_to_mnt, 
89                         size_updated,
90                         "",
91                         Clock.currTime().toUnixTime(),
92                         10000,
93                         txn);
94                 if (!size_updated)
95                     Thread.sleep( 200.msecs() );
96             }*/
97         }
98         else
99         {
100             int num_errors = copy_path(mgs, path, orig_move_to, remove_flag, tid);
101             if (num_errors == 0)
102                 remove_path(mgs, path);
103         }
104     }
105     catch (Exception exp)
106     {
107         shared msg = ConsoleMessage(
108                 SDL_Color(0xFF, 0x00, 0x00, 0xFF),
109                 format("Failed Move: %s", exp.msg),
110                 SDL_GetTicks()
111                 );
112         send(tid, msg);
113     }
114 
115     return 0;
116 }
117 
118 private void
119 start_move_paths(shared LsblkInfo[string] lsblk, immutable string[] paths, string move_to, bool remove, Tid tid)
120 {
121     writefln("Start moving %s, remove=%s", paths, remove);
122 
123     try {
124         FMGlobalState mgs = new FMGlobalState();
125         scope(exit)
126         {
127             destroy(mgs);
128         }
129 
130         mgs.lsblk = to!(LsblkInfo[string])(lsblk);
131 
132         string[] paths_dup = paths.dup;
133         sort!("a < b")(paths_dup);
134         foreach(path; paths_dup)
135         {
136             move_path(mgs, PathMnt(mgs.lsblk, path), move_to, remove, tid);
137         }
138     } catch (shared(Throwable) exc) {
139         send(tid, exc);
140     }
141 
142     writefln("Finish moving %s", paths);
143     send(tid, thisTid);
144 }
145 
146 int move_paths(GlobalState gs, immutable string[] paths, string move_to, bool remove)
147 {
148     foreach(tid, paths2; gs.movers)
149     {
150         if (paths2 == paths)
151         {
152             writefln("Move %s already in work", paths);
153             return 0;
154         }
155     }
156 
157     shared LsblkInfo[string] lsblk = to!(shared LsblkInfo[string])(gs.lsblk);
158     auto tid = spawn(&start_move_paths, lsblk, paths, move_to, remove, thisTid);
159     gs.movers[tid] = paths.dup();
160     return 0;
161 }
162 
163 void check_movers(GlobalState gs)
164 {
165     // Look check_scanners
166 }
167