dropbox-api-commandのファイル更新判定を変更する

Perlで実装されたDropbox操作コマンドです。

ディレクトリのsyncのために定期的にcronで実行して便利に使わせていただいていたのですが、ファイルの更新を「サイズが違う」あるいは「タイムスタンプが違う」のどちらかで判定しているので、古いファイルに同期してしまう問題があります。

普段は古いファイルをダウンロード(sync)される前に手動でpushして対応していたのですが、先ほど油断した隙に1時間の作業を全部ロールバックされてしまったので、さすがに何とかすることにしました。

   1114 sub has_change ($$) {
   1115     my ($local_path, $content) = @_;
   1116
   1117     my $remote_epoch = $strp->parse_datetime($content->{client_modified})->epoch;
   1118     my $local_epoch = $local_path->stat->mtime;
   1119     my $remote_size = $content->{size};
   1120     my $local_size = $local_path->stat->size;
   1121
   1122     if ($debug) {
   1123         printf "remote: %10s %10s %s\n", $remote_epoch, $remote_size, $content->{path_display};
   1124         printf "local:  %10s %10s %s\n", $local_epoch, $local_size, decode('locale_fs', $local_path);
   1125     }
   1126
   1127     if (($remote_size != $local_size) || ($remote_epoch != $local_epoch)) {
   1128         return 1;
   1129     }
   1130
   1131     return;
   1132 }

問題の部分はここ。

   1114 sub has_change ($$$) {
...
   1127 #    if (($remote_size != $local_size) || ($remote_epoch != $local_epoch)) {
   1128     if ($remote_size != $local_size){
   1129         if($is_upload){
   1130             return 1 if $remote_epoch < $local_epoch;
   1131         }
   1132         else{ # download
   1133             return 1 if $remote_epoch > $local_epoch;
   1134         }
   1135     }
   1136     return;
   1137 }

has_changedはダウンロードとアップロードの2箇所呼ばれるので、「ファイルが新しい場合に更新」を実現させようとすると不等号の向きが逆になります。のでフラグを追加。

$ grep -nE "has_change|^sub sync_upload|sub sync_download" /usr/local/bin/dropbox-api
720:sub sync_download {
764:            if ((!-f $local_path) || has_change($local_path, $content, 0)) {
872:sub sync_download_file {
884:    if ((!-f $local_path) || has_change($local_path, $content, 0)) {
927:sub sync_upload {
976:                if (has_change($local_path, $content, 1)) {
1050:sub sync_upload_file {
1091:        if (has_change($local_path, $content, 1)) {