macos-trash icon indicating copy to clipboard operation
macos-trash copied to clipboard

`Put back` only works for the first file

Open sindresorhus opened this issue 9 years ago • 39 comments

Continued from https://github.com/sindresorhus/trash/issues/24. This is a really weird issue.

Only the first file trashed with trashItemAtURL in a process will have the ability to Put back from the trash. I've narrowed down the code and the below still only adds Put back for the first file foo:

@import Foundation;

int main() {
    [[[NSFileManager alloc] init] trashItemAtURL:[NSURL URLWithString:@"file:///Users/sindresorhus/dev/osx-trash/foo"] resultingItemURL:nil error:nil];
    [[[NSFileManager alloc] init] trashItemAtURL:[NSURL URLWithString:@"file:///Users/sindresorhus/dev/osx-trash/bar"] resultingItemURL:nil error:nil];

    return 0;
}

I'm starting to think this is a OS X bug. Would appriciate being proved wrong, though. Gonna open an issue on radar when I get a chance, unless someone can figure this out.

sindresorhus avatar Oct 15 '15 08:10 sindresorhus

This is what I found out at StackOverflow:

http://stackoverflow.com/a/27847797

Let's try to pass an NSURL to resultingItemURL.

SamVerschueren avatar Oct 15 '15 08:10 SamVerschueren

Yeah, I've tried that too and lots of other things. Nothing. Debugged this for hours...

sindresorhus avatar Oct 15 '15 08:10 sindresorhus

Have you tried adding a sleep between two consecutive calls? Maybe something in the background can't follow the trash procedure and gets confused...

SamVerschueren avatar Oct 15 '15 08:10 SamVerschueren

Yup, also tried doing some other NSFileManager between, and also tried making the calls in different threads.

sindresorhus avatar Oct 15 '15 08:10 sindresorhus

@pornel Sorry for mentioning you, but you're the only the Obj-C person I know of. Any idea what's going on?

sindresorhus avatar Oct 15 '15 08:10 sindresorhus

Any particular reason why you allocate two file managers instead of using the same instance? (Not sure if it affects the problem, but worth trying).

thomassnielsen avatar Oct 15 '15 20:10 thomassnielsen

@thomassnielsen Just to make sure the problem is not with reusing the defaultManager. That's not the problem, though.

sindresorhus avatar Oct 16 '15 08:10 sindresorhus

@fcanas: After a deep 🐇 hole: Looks like a NSFileManager 🐛. Can workaround by having Finder delete via ScriptingBridge. - https://twitter.com/fcanas/status/654817376790167552

sindresorhus avatar Oct 16 '15 08:10 sindresorhus

Deleting via scriptingbridge is... messy. Let my try to repro and play with it a bit.


I can't even repro it working for the first file; nothing can be put back. Calling trash with a single file doesn't even work. Confirmed it's not even the directory that matters; it's any directory.

I tried figuring out where it's storing the original location of the file, but I can't find a PList or anything.

Qix- avatar Oct 16 '15 22:10 Qix-

The answer seems to lay within the .DS_Store file (~/.Trash/.DS_Store). Legend has it Apple has deprecated their use, but it seems to be the key here.

$ pwd
/src/sindresorhus.osx-trash
$ touch foo bar
$ <use finder to manually Move To Trash `foo`>
$ ./trash bar
$ xxd ~/.Trash/.DS_Store
. . . snip . . .
00001570: 0069 006e 0064 0072 0065 0073 006f 0072  .i.n.d.r.e.s.o.r
00001580: 0068 0075 0073 002e 006f 0073 0078 002d  .h.u.s...o.s.x.-
00001590: 0074 0072 0061 0073 0068 002f 0000 0003  .t.r.a.s.h./....
000015a0: 0066 006f 006f 7074 624e 7573 7472 0000  .f.o.optbNustr..
000015b0: 0003 0066 006f 006f 0000 0026 0047 006f  ...f.o.o
. . . snip . . .

ptbNustr is some sort of separator token

Upon further look, as I suspected, bar was nowhere to be seen in the .DS_Store, which means Trash doesn't know where the file came from; this is definitely a bug in [NSFileManager trashItemAtURL: resultingItemURL:error:]. Our workaround could be to edit the .DS_Store file manually, though there isn't a cocoa interface to do this; we'd have to manually do it ourselves.

Qix- avatar Oct 16 '15 23:10 Qix-

I filed a bug with Apple; bug 23153124. Don't think it's publicly viewable. I'll update here as I hear anything.

Probably want to work on a workaround for now.

Qix- avatar Oct 16 '15 23:10 Qix-

Oh, very interesting. Thanks for looking into this @Qix- and for filing the bug. Would you mind also filing it on https://openradar.appspot.com and pasting a link to it here?

sindresorhus avatar Oct 17 '15 07:10 sindresorhus

@gchriswill Why not Objective-C? ;)

As well, @sindresorhus has been doing a bit of C lately, not just for OS X. That's probably why.

Qix- avatar Oct 22 '15 07:10 Qix-

I initally wrote this in Swift, but had to rewrite it in Objective-C as the binary was several megabytes (because before Swift 2 the whole interpreter was embedded in the binary). Doesn't really matter anyways, though, as it's so little code.

sindresorhus avatar Oct 22 '15 07:10 sindresorhus

@sindresorhus Sorry I couldn't check that earlier. ImageOptim suffers from the same problem, and I'm pretty sure Put Back used to work for all files when I first wrote it, so it's a regression in OS X.

kornelski avatar Oct 23 '15 12:10 kornelski

sleep(10) between the calls "fixes" it, so there may be some kind of delayed flush in Finder. The problem still happens when I try to delete 1 file per process, by launching 2 processes, so it's a system-wide bug, not something limited to NSFileManager instance.

kornelski avatar Oct 23 '15 12:10 kornelski

@pornel could you write a quick POC for that? I'll add it to the bug report.

Qix- avatar Oct 23 '15 19:10 Qix-

The code at the top of the thread already shows the bug very well.

kornelski avatar Oct 23 '15 22:10 kornelski

@pornel with the sleep() call I mean.

Qix- avatar Oct 23 '15 22:10 Qix-

@pornel Oh, interesting. Thanks for chiming in.

sleep(2); is the shortest sleep that makes it work for me. sleep(1) and [NSThread sleepForTimeInterval:1.9] does not. So it seems there some kind of flush after 2 seconds.

sindresorhus avatar Oct 24 '15 07:10 sindresorhus

Still an issue in macOS Sierra...

sindresorhus avatar Sep 22 '16 18:09 sindresorhus

Let me check on the radar...

EDIT: Nothing. I've added information re: Sierra.

Qix- avatar Sep 22 '16 20:09 Qix-

Should we resort to creating a .DS_Store editor? There's a Perl implementation that we could port.

Qix- avatar Sep 22 '16 21:09 Qix-

Still nothing on the radar.

Qix- avatar Feb 05 '17 10:02 Qix-

I just stumbled upon this while debugging https://github.com/IngmarStein/Monolingual/ which suffers from the same bug. Thanks for your analysis and please keep us in the loop when (or if) the radar status changes.

IngmarStein avatar Feb 06 '17 21:02 IngmarStein

There's a Swift implementation of this function, maybe that has better chance of working on Sierra?

denrat avatar Apr 24 '17 16:04 denrat

@h0d I doubt that will make any difference. That Swift call uses the same Objective-C API underneath.

sindresorhus avatar Apr 24 '17 16:04 sindresorhus

^ Correct.

Qix- avatar Apr 24 '17 16:04 Qix-

Still having problem in 10.13.5. No "Put back" option appears on deleted files in Trash. Any news?

leanne63 avatar Jul 05 '18 21:07 leanne63