diff --git a/kittens/dnd/drop.go b/kittens/dnd/drop.go index 18e4db564..eb003e122 100644 --- a/kittens/dnd/drop.go +++ b/kittens/dnd/drop.go @@ -121,7 +121,7 @@ func uniqify_child_names(names []string, is_case_sensitive_filesystem bool) []st return names } -func (d *remote_dir_entry) add_remote_data(data []byte, output_buf []byte, has_more bool, parent *remote_dir_entry, is_case_sensitive_filesystem bool) error { +func (d *remote_dir_entry) add_remote_data(data []byte, output_buf []byte, has_more bool, is_case_sensitive_filesystem bool) error { if len(data) > 0 { for chunk, derr := range d.b64_decoder.Decode(data, output_buf) { if derr != nil { @@ -143,7 +143,6 @@ func (d *remote_dir_entry) add_remote_data(data []byte, output_buf []byte, has_m d.dest.Close() d.dest = nil d.base_dir = d.base_dir.unref() - parent.num_children_finished++ }() if dest, ok := d.dest.(*bufferWriteCloser); ok { if d.item_type == 1 { @@ -199,9 +198,9 @@ type drop_status struct { reading_data bool is_remote_client bool - root_remote_dir *remote_dir_entry - open_remote_dir *remote_dir_entry - pending_remote_dirs []*remote_dir_entry + root_remote_dir *remote_dir_entry + open_remote_dir *remote_dir_entry + current_remote_entry *remote_dir_entry // used for m=1 only } var reset_drop_status = drop_status{cell_x: -1, cell_y: -1} @@ -357,7 +356,6 @@ func (dnd *dnd) on_drop_move(cell_x, cell_y int, has_more bool, offered_mimes st return } -var current_remote_entry *remote_dir_entry var drop_buf []byte func (dnd *dnd) on_remote_drop_data(cmd DC) (err error) { @@ -366,7 +364,7 @@ func (dnd *dnd) on_remote_drop_data(cmd DC) (err error) { return fmt.Errorf("got a remote data response form the terminal without an open remote dir") } if cmd.X == 0 && cmd.Y == 0 && cmd.Yp == 0 { - if current_remote_entry == nil { + if drop_status.current_remote_entry == nil { return fmt.Errorf("got a remote data response form the terminal without a current remote entry") } } else { @@ -374,27 +372,34 @@ func (dnd *dnd) on_remote_drop_data(cmd DC) (err error) { if num < 0 || num >= len(drop_status.open_remote_dir.children) { return fmt.Errorf("got a remote data response from the terminal for an entry that does not exist") } - current_remote_entry = drop_status.open_remote_dir.children[num] + drop_status.current_remote_entry = drop_status.open_remote_dir.children[num] } - if current_remote_entry.dest == nil { - current_remote_entry.item_type = cmd.Xp + e := drop_status.current_remote_entry + if e.dest == nil { + e.item_type = cmd.Xp switch cmd.Xp { case 0: - f, err := utils.CreateAt(drop_status.open_remote_dir.base_dir.handle, current_remote_entry.name) + f, err := utils.CreateAt(e.base_dir.handle, e.name) if err != nil { return err } - current_remote_entry.dest = f + e.dest = f default: - current_remote_entry.dest = &bufferWriteCloser{&bytes.Buffer{}} + e.dest = &bufferWriteCloser{&bytes.Buffer{}} } } if sz := max(4096, len(cmd.Payload)+4); len(drop_buf) < sz { drop_buf = make([]byte, sz) } - if err = current_remote_entry.add_remote_data(cmd.Payload, drop_buf, cmd.Has_more, drop_status.open_remote_dir, dnd.is_case_sensitive_filesystem); err != nil { + if err = e.add_remote_data(cmd.Payload, drop_buf, cmd.Has_more, dnd.is_case_sensitive_filesystem); err != nil { return err } + if e.dest == nil { // this entry is finished + drop_status.open_remote_dir.num_children_finished++ + if e.item_type != 0 && e.item_type != 1 { + // TODO: request the children + } + } return nil } diff --git a/kittens/dnd/main.go b/kittens/dnd/main.go index 108f62300..fcb59a9a9 100644 --- a/kittens/dnd/main.go +++ b/kittens/dnd/main.go @@ -51,20 +51,22 @@ type DC = loop.DndCommand type dir_handle struct { handle *os.File - refcnt int32 + refcnt atomic.Int32 } func new_dir_handle(x *os.File) *dir_handle { - return &dir_handle{x, 1} + ans := dir_handle{x, atomic.Int32{}} + ans.refcnt.Store(1) + return &ans } func (d *dir_handle) newref() *dir_handle { - atomic.AddInt32(&d.refcnt, 1) + d.refcnt.Add(1) return d } func (d *dir_handle) unref() *dir_handle { - if atomic.AddInt32(&d.refcnt, -1) <= 0 { + if d.refcnt.Add(-1) <= 0 { d.handle.Close() d.handle = nil } diff --git a/kitty/dnd.c b/kitty/dnd.c index d6167b889..05711fad9 100644 --- a/kitty/dnd.c +++ b/kitty/dnd.c @@ -668,7 +668,6 @@ get_nth_file_url(const char *uri_list, size_t uri_list_sz, int n, char **path_ou p = eol + 1; while (*p == '\r' || *p == '\n') p++; } - if (!found_line) { *error_out = "ENOENT"; return false; } /* Must be a file:// URL */ @@ -695,10 +694,9 @@ get_nth_file_url(const char *uri_list, size_t uri_list_sz, int n, char **path_ou char resolved[PATH_MAX]; if (!realpath(path, resolved)) { switch (errno) { - case ENOENT: case ENOTDIR: *error_out = "ENOENT"; break; - case EACCES: case EPERM: *error_out = "EPERM"; break; - case ELOOP: *error_out = "ENOENT"; break; - default: *error_out = "EINVAL"; break; + case ENOENT: case ENOTDIR: case ELOOP: *error_out = "ENOENT"; break; + case EACCES: case EPERM: *error_out = "EPERM"; break; + default: *error_out = "EINVAL"; break; } return false; } @@ -951,7 +949,7 @@ drop_send_dir_listing(Window *w, const char *path) { queue_payload_to_child(w->id, w->drop.client_id, &w->drop.pending, hdr, hdr_sz, NULL, 0, true); } -/* Handle a t=s request: send the file/directory at URI-list index idx. +/* Send the file/directory at URI-list index idx. * Returns true if completed synchronously, false if async file I/O started. */ static bool do_drop_request_uri_data(Window *w, int32_t mime_idx, int32_t file_idx) { diff --git a/kitty_tests/dnd_kitten.py b/kitty_tests/dnd_kitten.py index 82e5b9f60..9b2d8f0c7 100644 --- a/kitty_tests/dnd_kitten.py +++ b/kitty_tests/dnd_kitten.py @@ -42,7 +42,7 @@ def w(sz, *path): f.write(b'x' * sz) os.makedirs(join('d1', 'sd', 'ssd')) os.mkdir(join('d2')) - os.symlink('/does-not-exist', join('s1')) + # os.symlink('/does-not-exist', join('s1')) os.symlink('d1', join('sd')) os.symlink('/', join('sr')) os.symlink('../d1', join('d1', 'sr'))