Nous sommes de plus en plus nombreux à utiliser Dropbox pour travailler à plusieurs sur des documents. C’est génial, le service est presque transparent … sauf qu’un jour, forcément, vous vous retrouverez avec des dossiers ou des fichiers en conflit.
Exemple, vous stockez un budget au format xls, que plusieurs personnes vont éditer simultanément … et enregistrer. Et là c’est le drame ! Dropbox ne sait plus quel est le bon fichier, ne sait pas les fusionner. Il va donc créer des fichiers avec une tag “en conflit” ou en anglais “conflicted”.
Tant que vous n’en avez que quelques uns, cela ce gère assez facilement à la main … mais à longue on peut vite se faire dépasser par ces multiples doublons.
J’ai cherché des solutions, et comme d’habitude, je n’ai pas trouvé tout à fait ce que je voulais. Du coup je me suis lancé dans une application en Applescript pour détecter les éléments en conflit et leur appliquer un traitement, au choix :
- les ouvrir dans le Finder,
- les mettre à la Corbeille,
- les déplacer dans un dossier (si possible hors Dropbox) de votre choix.
La première ligne de mon code est un commande shell qui recherche les fichiers potentiellement en conflit. Je me suis limité à rechercher selon les tag ‘conflicted’ (en anglais) et ‘en conflit’ (en français). Si vous travaillez avec des personnes ayant le programme installé dans une autre langue, potentiellement des conflits peuvent être générés dans cette nouvelle langue … et il faudra donc adapter cette première ligne de code en conséquence.
Pour pousser le vice, j’utilise des notifications Growl, que vous pouvez rediriger vers votre centre de notifications. J’ai également ajouté un support pour une notification en cas de mise à jour de cette application.
Vous pouvez télécharger l’application complète ici : https://github.com/yvangodard/DropboxConflictsSolver/archive/master.zip et me faire remonter les bugs, corrections ajouts sur https://github.com/yvangodard/DropboxConflictsSolver. S’il y a des volontaires, je peux rapidement ajouter le support multilingue de l’application.
Voici l’extrait central du code …
do shell script "LIST_CONFLITS=$(mktemp /tmp/liste_conflicted.XXXXX); basename $LIST_CONFLITS" set LIST_CONFLITS to "/tmp/" & result set command to "find -L ~/Dropbox \\( -path \"*.dropbox.cache*\" -prune \\) -o \\( -path \"*(Copie de * en conflit [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]*\" -print \\) >> " & LIST_CONFLITS & " ; find -L ~/Dropbox \\( -path \"*.dropbox.cache*\" -prune \\) -o \\( -path \"*(Copie en conflit de * [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]*\" -print \\) >> " & LIST_CONFLITS & " ; find -L ~/Dropbox \\( -path \"*.dropbox.cache*\" -prune \\) -o \\( -path \"*(*'s conflicted copy [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]*\" -print \\) >> " & LIST_CONFLITS do shell script command set command2 to "cat " & LIST_CONFLITS & " | awk '{if (x[$0] != \"\") next ; print $0 ; x[$0]=$0}' | sort -u >> " & LIST_CONFLITS & "new ; rm " & LIST_CONFLITS & " ; mv " & LIST_CONFLITS & "new " & LIST_CONFLITS do shell script command2 do shell script "cat " & LIST_CONFLITS set Liste to result set founditems to paragraphs of Liste as list set NumberOfConflicts to count items in founditems if NumberOfConflicts = 0 then display dialog "Vous n'avez aucun élément en conflit dans votre dossier Dropbox." with icon 1 buttons {"Terminer"} default button {"Terminer"} set MessageGrowl to "Vous n'aviez aucun élément en conflit dans votre dossier Dropbox." & return & "Traitement terminé." else if NumberOfConflicts > 0 then set ButtunZero to button returned of (display dialog "Voulez-vous AFFICHER DANS VOTRE FINDER ou TRAITER (déplacer ou supprimer) les éléments en conflit détectés ?" with icon 1 buttons {"Afficher dans le Finder", "Traiter", "Annuler"} default button "Annuler") if ButtunZero = "Annuler" then else if ButtunZero = "Afficher dans le Finder" then repeat with currFile in founditems set currFilePosix to POSIX file currFile tell application "Finder" to make new Finder window to currFilePosix end repeat if NumberOfConflicts = 1 then set MessageGrowl to "Traitement effectué, " & NumberOfConflicts & " élément ouvert dans votre Finder, à vous de jouer !" else if NumberOfConflicts > 1 then set MessageGrowl to "Traitement effectué, " & NumberOfConflicts & " éléments ouverts dans votre Finder, à vous de jouer !" end if else if ButtunZero = "Traiter" then if NumberOfConflicts = 1 then set ButtunPressed to button returned of (display alert "Vous avez " & NumberOfConflicts & " élément en conflit dans votre dossier Dropbox :" message Liste buttons {"Supprimer", "Déplacer", "Annuler"} default button "Annuler" as critical) if ButtunPressed = "Annuler" then set MessageGrowl to "Erreur :" & return & "Vous avez annulé le processus de traitement." else if ButtunPressed = "Déplacer" then display dialog "Choisissez le dossier de destination dans la fenêtre de dialogue suivante." with icon 1 buttons {"Continuer"} default button {"Continuer"} set DestinationFolder to choose folder ["Choisissez le dossier de destination."] do shell script "mv " & quoted form of Liste & " " & quoted form of (POSIX path of DestinationFolder) display alert "Le déplacement de l'élément a été effectué dans le dossier suivant :" message (POSIX path of DestinationFolder) buttons {"Terminer"} default button "Terminer" as critical set MessageGrowl to "Traitement effectué, 1 élément déplacé dans :" & return & (POSIX path of DestinationFolder) else if ButtunPressed = "Supprimer" then do shell script "mv " & quoted form of Liste & " ~/.Trash/" display dialog "Le déplacement a correctement été effectué dans votre corbeille." with icon 1 buttons {"Terminer"} default button {"Terminer"} set MessageGrowl to "Traitement effectué, 1 élément déplacé dans votre corbeille." end if else set ButtunPressed to button returned of (display dialog "Vous avez " & NumberOfConflicts & " éléments en conflit dans votre dossier Dropbox." & return & ¬ "Que voulez-vous faire ?" with icon 1 buttons {"Tout supprimer", "Tout déplacer", "Choisir individuellement"} default button "Choisir individuellement") if ButtunPressed = "Tout supprimer" then set numero to "0" repeat until numero = NumberOfConflicts set numero to numero + 1 set FichierEnCours to paragraph numero of Liste do shell script "mv " & quoted form of FichierEnCours & " ~/.Trash/" end repeat display dialog "Le déplacement des éléments a été correctement effectué dans votre corbeille." with icon 1 buttons {"Terminer"} default button {"Terminer"} set MessageGrowl to "Traitement effectué, " & NumberOfConflicts & " éléments déplacés dans votre corbeille." else if ButtunPressed = "Tout déplacer" then display dialog "Choisissez le dossier de destination dans la fenêtre de dialogue suivante." with icon 1 buttons {"Continuer"} default button {"Continuer"} set DestinationFolder to choose folder ["Choisissez le dossier de destination."] set numero to "0" repeat until numero = NumberOfConflicts set numero to numero + 1 set FichierEnCours to paragraph numero of Liste do shell script "mv " & quoted form of FichierEnCours & " " & quoted form of (POSIX path of DestinationFolder) end repeat display alert "Le déplacement des éléments a été effectué dans le dossier suivant :" message (POSIX path of DestinationFolder) buttons {"Terminer"} default button "Terminer" as critical set MessageGrowl to "Traitement effectué, " & NumberOfConflicts & " éléments déplacés dans :" & return & (POSIX path of DestinationFolder) else if ButtunPressed = "Choisir individuellement" then set numero to "0" repeat until numero = NumberOfConflicts set numero to numero + 1 set FichierEnCours to paragraph numero of Liste set ButtunPressed to button returned of (display alert "Traitement de l'élément n°" & numero & return & ¬ "Que voulez-vous faire pour l'élément suivant ?" message FichierEnCours buttons {"Supprimer", "Déplacer", "Annuler"} default button "Annuler" as critical) if ButtunPressed = "Annuler" then else if ButtunPressed = "Déplacer" then display dialog "Choisissez le dossier de destination dans la fenêtre de dialogue suivante." with icon 1 buttons {"Continuer"} default button {"Continuer"} set DestinationFolder to choose folder ["Choisissez le dossier de destination."] do shell script "mv " & quoted form of FichierEnCours & " " & quoted form of (POSIX path of DestinationFolder) else if ButtunPressed = "Supprimer" then do shell script "mv " & quoted form of FichierEnCours & " ~/.Trash/" end if end repeat set MessageGrowl to "Traitement mixte de " & NumberOfConflicts & " éléments en conflit effectué." end if end if end if end if do shell script "rm " & LIST_CONFLITS tell application "System Events" set isRunning to (count of (every process whose bundle identifier is "com.Growl.GrowlHelperApp")) > 0 end tell if isRunning then tell application id "com.Growl.GrowlHelperApp" set the allNotificationsList to ¬ {"Dropbox Conflicts Solver"} set the enabledNotificationsList to ¬ {"Dropbox Conflicts Solver"} register as application ¬ "Dropbox Conflicts Solver" all notifications allNotificationsList ¬ default notifications enabledNotificationsList ¬ icon of application "Dropbox.app" notify with name ¬ "Dropbox Conflicts Solver" title ¬ "Dropbox" description ¬ MessageGrowl application name "Dropbox Conflicts Solver" end tell end if
N’hésitez pas à me faire vos retours, vos suggestions.
En stock, j’ai également créé un petit installeur qui ajoute une recherche périodique automatique (via LaunchAgent), vous pouvez le télécharger ici.