Hi Guys:
I find a bug in Arcanist. I used //arc diff// to generate a revision, I found arc generate a wrong GIT patch, cause I cannot use //arc patch// to apply diff to local branch.
After a long time debug, I find that arc generate GIT patch is different than// git diff// does. there is one block comment in diff.c which belong to GIT source tree
```
3186 if (!pgm &&
3187 DIFF_FILE_VALID(one) && DIFF_FILE_VALID(two) &&
3188 (S_IFMT & one->mode) != (S_IFMT & two->mode)) {
3189 /*
3190 * a filepair that changes between file and symlink
3191 * needs to be split into deletion and creation.
3192 */
3193 struct diff_filespec *null = alloc_filespec(two->path);
3194 run_diff_cmd(NULL, name, other, attr_path,
3195 one, null, &msg, o, p);
3196 free(null);
3197 strbuf_release(&msg);
3198
3199 null = alloc_filespec(one->path);
3200 run_diff_cmd(NULL, name, other, attr_path,
3201 null, two, &msg, o, p);
3202 free(null);
3203 }
```
this comment shows git treat file type change more carefully. if change between file and symlink, it will be split into two changes. but arc doesn't.
```
// file: src/parser/ArcanistBundle.php
public function toGitPatch() {
$eol = $this->getEOL('git');
$result = array();
$changes = $this->getChanges();
......
foreach ($changes as $change) {
$type = $change->getType();
$file_type = $change->getFileType();
......
$old_mode = idx($change->getOldProperties(), 'unix:filemode', '100644');
$new_mode = idx($change->getNewProperties(), 'unix:filemode', '100644');
......
if ($type == ArcanistDiffChangeType::TYPE_COPY_HERE ||
$type == ArcanistDiffChangeType::TYPE_MOVE_HERE ||
$type == ArcanistDiffChangeType::TYPE_COPY_AWAY ||
$type == ArcanistDiffChangeType::TYPE_CHANGE) {
if ($old_mode !== $new_mode) {
$result[] = "old mode {$old_mode}".$eol;
$result[] = "new mode {$new_mode}".$eol;
}
}
```
this code show arc just output old file mode and new file mode to patch file. for my case, it looks like this:
```
diff --git a/projects/lib/libprotobuf.so.7 b/projects/lib/libprotobuf.so.7
old mode 100755
new mode 120000
index 3f5f2a5be18a8fb65033b21a6777838475a98386..64f9ac68837117655ef3ced85f18c71c86d163b3
GIT binary patch
literal 20
bc$~}0Oe!eKFUe0TP17sR*E82M&@%u4QWOT-
literal 6789021
zc$|E_2|QHa|Hpr4ERD6X?-^?-TTvt$A|z|bR@tJEWNBAp$&!>MgcMO(Dv^{WiG)fa
zr6>`llq{u1$^Y$h&-}kL{{8;*csxI^_j%oO&pq2c_ukRm&k>Ui>xcvbM*py22H0H6
zU6Jj-G!^;#lD+=lJXA~vV}t)HVsiiGWyAjOkH+qWOp0NY|Nc9-ANyQDLq1KNNef-@
zWXl$eX+I*`&+IC`pV?J)ChbQ}p(_dPZSyYFn-#P^ljpzmd_9gDN>^62pDpai{{Pdy
```
And finally. //arc patch// will failed. cause //arc patch// use // git apply// to apply diff. // git apply// will check is that patch validate by the following code:
```
// file: builtin/apply.c
// function: check_patch()
3763 if (new_name && old_name) {
3764 int same = !strcmp(old_name, new_name);
3765 if (!patch->new_mode)
3766 patch->new_mode = patch->old_mode;
3767 if ((patch->old_mode ^ patch->new_mode) & S_IFMT) {
3768 if (same)
3769 return error(_("new mode (%o) of %s does not "
3770 "match old mode (%o)"),
3771 patch->new_mode, new_name,
3772 patch->old_mode);
3773 else
3774 return error(_("new mode (%o) of %s does not "
3775 "match old mode (%o) of %s"),
3776 patch->new_mode, new_name,
3777 patch->old_mode, old_name);
3778 }
3779 }
```
So this bug is obviously now. the last thing is to change the code in src/parser/ArcanistBundle.php. BUT, I'm not a phper. I can read the php code just because it looks like C. PLS fix it, it has already blocked me long time. thanks.