@@ -101,15 +101,20 @@ func (d *downstream) mainLoop() error {
101101
102102 for {
103103 removeFiles := d .cloneFileMap ()
104+ removeFilesLen := len (removeFiles )
104105
105106 // Check for changes remotely
106107 createFiles , err := d .collectChanges (removeFiles )
107108 if err != nil {
108109 return errors .Trace (err )
109110 }
110111
111- amountChanges := len (createFiles ) + len (removeFiles )
112+ // There is an issue with collect changes, hence we return an error
113+ if removeFilesLen == len (removeFiles ) {
114+ return errors .New ("Sync cannot execute find command remotely" )
115+ }
112116
117+ amountChanges := len (createFiles ) + len (removeFiles )
113118 if lastAmountChanges > 0 && amountChanges == lastAmountChanges {
114119 err = d .applyChanges (createFiles , removeFiles )
115120 if err != nil {
@@ -150,6 +155,131 @@ func (d *downstream) cloneFileMap() map[string]*fileInformation {
150155 return mapClone
151156}
152157
158+ func (d * downstream ) collectChanges (removeFiles map [string ]* fileInformation ) ([]* fileInformation , error ) {
159+ createFiles := make ([]* fileInformation , 0 , 128 )
160+
161+ // Write find command to stdin pipe
162+ cmd := getFindCommand (d .config .DestPath )
163+ _ , err := d .stdinPipe .Write ([]byte (cmd ))
164+ if err != nil {
165+ return nil , errors .Trace (err )
166+ }
167+
168+ buf := make ([]byte , 0 , 512 )
169+ overlap := ""
170+ done := false
171+
172+ for done == false {
173+ n , err := d .stdoutPipe .Read (buf [:cap (buf )])
174+ buf = buf [:n ]
175+
176+ if n == 0 {
177+ if err == nil {
178+ continue
179+ }
180+ if err == io .EOF {
181+ return nil , errors .Trace (fmt .Errorf ("[Downstream] Stream closed unexpectedly" ))
182+ }
183+
184+ return nil , errors .Trace (err )
185+ }
186+
187+ // Error reading from stdout
188+ if err != nil && err != io .EOF {
189+ return nil , errors .Trace (err )
190+ }
191+
192+ done , overlap , err = d .parseLines (string (buf ), overlap , & createFiles , removeFiles )
193+ if err != nil {
194+ if _ , ok := err .(parsingError ); ok {
195+ time .Sleep (time .Second * 4 )
196+ return d .collectChanges (removeFiles )
197+ }
198+
199+ // No trace here because it could be a parsing error
200+ return nil , errors .Trace (err )
201+ }
202+ }
203+
204+ return createFiles , nil
205+ }
206+
207+ func (d * downstream ) parseLines (buffer , overlap string , createFiles * []* fileInformation , removeFiles map [string ]* fileInformation ) (bool , string , error ) {
208+ lines := strings .Split (buffer , "\n " )
209+
210+ for index , element := range lines {
211+ line := ""
212+
213+ if index == 0 {
214+ if len (lines ) > 1 {
215+ line = overlap + element
216+ } else {
217+ overlap += element
218+ }
219+ } else if index == len (lines )- 1 {
220+ overlap = element
221+ } else {
222+ line = element
223+ }
224+
225+ if line == EndAck || overlap == EndAck {
226+ return true , overlap , nil
227+ } else if line == ErrorAck || overlap == ErrorAck {
228+ return true , "" , parsingError {
229+ msg : "Parsing Error" ,
230+ }
231+ } else if line != "" {
232+ err := d .evaluateFile (line , createFiles , removeFiles )
233+
234+ if err != nil {
235+ return true , "" , errors .Trace (err )
236+ }
237+ }
238+ }
239+
240+ return false , overlap , nil
241+ }
242+
243+ func (d * downstream ) evaluateFile (fileline string , createFiles * []* fileInformation , removeFiles map [string ]* fileInformation ) error {
244+ d .config .fileIndex .fileMapMutex .Lock ()
245+ defer d .config .fileIndex .fileMapMutex .Unlock ()
246+
247+ fileInformation , err := parseFileInformation (fileline , d .config .DestPath )
248+
249+ // Error parsing line
250+ if err != nil {
251+ return errors .Trace (err )
252+ }
253+
254+ // No file found
255+ if fileInformation == nil {
256+ return nil
257+ }
258+
259+ // File found don't delete it
260+ delete (removeFiles , fileInformation .Name )
261+
262+ // Update mode, gid & uid if exists
263+ if d .config .fileIndex .fileMap [fileInformation .Name ] != nil {
264+ d .config .fileIndex .fileMap [fileInformation .Name ].RemoteMode = fileInformation .RemoteMode
265+ d .config .fileIndex .fileMap [fileInformation .Name ].RemoteGID = fileInformation .RemoteGID
266+ d .config .fileIndex .fileMap [fileInformation .Name ].RemoteUID = fileInformation .RemoteUID
267+ }
268+
269+ // Exclude symlinks
270+ if fileInformation .IsSymbolicLink {
271+ // Add them to the fileMap though
272+ d .config .fileIndex .fileMap [fileInformation .Name ] = fileInformation
273+ }
274+
275+ // Should we download the file / folder?
276+ if shouldDownload (fileInformation , d .config ) {
277+ * createFiles = append (* createFiles , fileInformation )
278+ }
279+
280+ return nil
281+ }
282+
153283func (d * downstream ) applyChanges (createFiles []* fileInformation , removeFiles map [string ]* fileInformation ) error {
154284 var err error
155285
@@ -384,129 +514,3 @@ func (d *downstream) createFolders(createFolders []*fileInformation) {
384514 }
385515 }
386516}
387-
388- func (d * downstream ) collectChanges (removeFiles map [string ]* fileInformation ) ([]* fileInformation , error ) {
389- createFiles := make ([]* fileInformation , 0 , 128 )
390-
391- // Write find command to stdin pipe
392- cmd := getFindCommand (d .config .DestPath )
393- _ , err := d .stdinPipe .Write ([]byte (cmd ))
394- if err != nil {
395- return nil , errors .Trace (err )
396- }
397-
398- buf := make ([]byte , 0 , 512 )
399- overlap := ""
400- done := false
401-
402- for done == false {
403- n , err := d .stdoutPipe .Read (buf [:cap (buf )])
404- buf = buf [:n ]
405-
406- if n == 0 {
407- if err == nil {
408- continue
409- }
410-
411- if err == io .EOF {
412- return nil , errors .Trace (fmt .Errorf ("[Downstream] Stream closed unexpectedly" ))
413- }
414-
415- return nil , errors .Trace (err )
416- }
417-
418- // Error reading from stdout
419- if err != nil && err != io .EOF {
420- return nil , errors .Trace (err )
421- }
422-
423- done , overlap , err = d .parseLines (string (buf ), overlap , & createFiles , removeFiles )
424- if err != nil {
425- if _ , ok := err .(parsingError ); ok {
426- time .Sleep (time .Second * 4 )
427- return d .collectChanges (removeFiles )
428- }
429-
430- // No trace here because it could be a parsing error
431- return nil , errors .Trace (err )
432- }
433- }
434-
435- return createFiles , nil
436- }
437-
438- func (d * downstream ) parseLines (buffer , overlap string , createFiles * []* fileInformation , removeFiles map [string ]* fileInformation ) (bool , string , error ) {
439- lines := strings .Split (buffer , "\n " )
440-
441- for index , element := range lines {
442- line := ""
443-
444- if index == 0 {
445- if len (lines ) > 1 {
446- line = overlap + element
447- } else {
448- overlap += element
449- }
450- } else if index == len (lines )- 1 {
451- overlap = element
452- } else {
453- line = element
454- }
455-
456- if line == EndAck || overlap == EndAck {
457- return true , overlap , nil
458- } else if line == ErrorAck || overlap == ErrorAck {
459- return true , "" , parsingError {
460- msg : "Parsing Error" ,
461- }
462- } else if line != "" {
463- err := d .evaluateFile (line , createFiles , removeFiles )
464-
465- if err != nil {
466- return true , "" , errors .Trace (err )
467- }
468- }
469- }
470-
471- return false , overlap , nil
472- }
473-
474- func (d * downstream ) evaluateFile (fileline string , createFiles * []* fileInformation , removeFiles map [string ]* fileInformation ) error {
475- d .config .fileIndex .fileMapMutex .Lock ()
476- defer d .config .fileIndex .fileMapMutex .Unlock ()
477-
478- fileInformation , err := parseFileInformation (fileline , d .config .DestPath )
479-
480- // Error parsing line
481- if err != nil {
482- return errors .Trace (err )
483- }
484-
485- // No file found
486- if fileInformation == nil {
487- return nil
488- }
489-
490- // File found don't delete it
491- delete (removeFiles , fileInformation .Name )
492-
493- // Update mode, gid & uid if exists
494- if d .config .fileIndex .fileMap [fileInformation .Name ] != nil {
495- d .config .fileIndex .fileMap [fileInformation .Name ].RemoteMode = fileInformation .RemoteMode
496- d .config .fileIndex .fileMap [fileInformation .Name ].RemoteGID = fileInformation .RemoteGID
497- d .config .fileIndex .fileMap [fileInformation .Name ].RemoteUID = fileInformation .RemoteUID
498- }
499-
500- // Exclude symlinks
501- if fileInformation .IsSymbolicLink {
502- // Add them to the fileMap though
503- d .config .fileIndex .fileMap [fileInformation .Name ] = fileInformation
504- }
505-
506- // Should we download the file / folder?
507- if shouldDownload (fileInformation , d .config ) {
508- * createFiles = append (* createFiles , fileInformation )
509- }
510-
511- return nil
512- }
0 commit comments