def __upload(rel_path_or_buf):
            # Its a buf!
            if type(rel_path_or_buf) == dict:
                return self._upload(utils.get_full_path(rel_path_or_buf['path']), rel_path_or_buf.get('buf'))

            # Its a rel path!
            buf_id = self.paths_to_ids.get(rel_path_or_buf)
            text = self.bufs.get(buf_id, {}).get('buf')
            # Only upload stuff that's not in self.bufs (new bufs). We already took care of everything else.
            if text is not None:
                return len(text)
            return self._upload(utils.get_full_path(rel_path_or_buf), self.get_view_text_by_path(rel_path_or_buf))
Example #2
0
        def __upload(rel_path_or_buf):
            # Its a buf!
            if type(rel_path_or_buf) == dict:
                return self._upload(utils.get_full_path(rel_path_or_buf['path']), rel_path_or_buf.get('buf'))

            # Its a rel path!
            buf_id = self.paths_to_ids.get(rel_path_or_buf)
            text = self.bufs.get(buf_id, {}).get('buf')
            # Only upload stuff that's not in self.bufs (new bufs). We already took care of everything else.
            if text is not None:
                return len(text)
            return self._upload(utils.get_full_path(rel_path_or_buf), self.get_view_text_by_path(rel_path_or_buf))
 def _on_rename_buf(self, data):
     del self.paths_to_ids[data['old_path']]
     self.paths_to_ids[data['path']] = data['id']
     new = utils.get_full_path(data['path'])
     old = utils.get_full_path(data['old_path'])
     new_dir = os.path.split(new)[0]
     if new_dir:
         utils.mkdir(new_dir)
     view = self.get_view(data['id'])
     if view:
         view.rename(new)
     else:
         os.rename(old, new)
     self.bufs[data['id']]['path'] = data['path']
Example #4
0
 def _on_rename_buf(self, data):
     del self.paths_to_ids[data['old_path']]
     self.paths_to_ids[data['path']] = data['id']
     new = utils.get_full_path(data['path'])
     old = utils.get_full_path(data['old_path'])
     new_dir = os.path.split(new)[0]
     if new_dir:
         utils.mkdir(new_dir)
     view = self.get_view(data['id'])
     if view:
         view.rename(new)
     else:
         os.rename(old, new)
     self.bufs[data['id']]['path'] = data['path']
Example #5
0
 def _on_rename_buf(self, data):
     # This can screw up if someone else renames the buffer around the same time as us. Oh well.
     msg.debug('asdf %s' % data)
     buf = self.get_buf_by_path(utils.get_full_path(data['old_path']))
     if buf:
         return super(AgentConnection, self)._on_rename_buf(data)
     msg.debug('We already renamed %s. Skipping' % data['old_path'])
Example #6
0
 def __upload(rel_path):
     buf_id = self.paths_to_ids.get(rel_path)
     text = self.bufs.get(buf_id, {}).get('buf')
     # Only upload stuff that's not in self.bufs (new bufs). We already took care of everything else.
     if text is not None:
         return len(text)
     return self._upload(utils.get_full_path(rel_path), self.get_view_text_by_path(rel_path))
Example #7
0
 def _on_rename_buf(self, data):
     # This can screw up if someone else renames the buffer around the same time as us. Oh well.
     msg.debug('asdf %s' % data)
     buf = self.get_buf_by_path(utils.get_full_path(data['old_path']))
     if buf:
         return super(AgentConnection, self)._on_rename_buf(data)
     msg.debug('We already renamed %s. Skipping' % data['old_path'])
Example #8
0
    def _scan_dir(self, bufs, ig, read_only):
        changed_bufs = []
        missing_bufs = []
        new_files = set()

        if not read_only:
            new_files = set([utils.to_rel_path(x) for x in ig.list_paths()])

        for buf_id, buf in bufs.items():
            buf_id = int(buf_id)  # json keys must be strings
            buf_path = utils.get_full_path(buf['path'])
            new_dir = os.path.dirname(buf_path)
            utils.mkdir(new_dir)
            self.bufs[buf_id] = buf
            self.paths_to_ids[buf['path']] = buf_id

            view = self.get_view(buf_id)
            if view and not view.is_loading() and buf['encoding'] == 'utf8':
                view_text = view.get_text()
                view_md5 = hashlib.md5(view_text.encode('utf-8')).hexdigest()
                buf['buf'] = view_text
                buf['view'] = view
                G.VIEW_TO_HASH[view.native_id] = view_md5
                if view_md5 == buf['md5']:
                    msg.debug('md5 sum matches view. not getting buffer ',
                              buf['path'])
                else:
                    changed_bufs.append(buf)
                    buf['md5'] = view_md5
                continue

            try:
                if buf['encoding'] == 'utf8':
                    if io:
                        buf_fd = io.open(buf_path, 'Urt', encoding='utf8')
                        buf_buf = buf_fd.read()
                    else:
                        buf_fd = open(buf_path, 'rb')
                        buf_buf = buf_fd.read().decode('utf-8').replace(
                            '\r\n', '\n')
                    md5 = hashlib.md5(buf_buf.encode('utf-8')).hexdigest()
                else:
                    buf_fd = open(buf_path, 'rb')
                    buf_buf = buf_fd.read()
                    md5 = hashlib.md5(buf_buf).hexdigest()
                buf_fd.close()
                buf['buf'] = buf_buf
                if md5 == buf['md5']:
                    msg.debug('md5 sum matches. not getting buffer ',
                              buf['path'])
                else:
                    msg.debug('md5 differs. possibly getting buffer later ',
                              buf['path'])
                    changed_bufs.append(buf)
                    buf['md5'] = md5
            except Exception as e:
                msg.debug('Error calculating md5 for ', buf['path'], ', ',
                          str_e(e))
                missing_bufs.append(buf)
        return changed_bufs, missing_bufs, new_files
Example #9
0
 def __upload(rel_path):
     buf_id = self.paths_to_ids.get(rel_path)
     text = self.bufs.get(buf_id, {}).get('buf')
     # Only upload stuff that's not in self.bufs (new bufs). We already took care of everything else.
     if text is not None:
         return len(text)
     return self._upload(utils.get_full_path(rel_path), self.get_view_text_by_path(rel_path))
Example #10
0
 def _on_delete_buf(self, data):
     path = utils.get_full_path(data['path'])
     try:
         utils.rm(path)
     except Exception:
         pass
     user_id = data.get('user_id')
     username = self.get_username_by_id(user_id)
     msg.log('%s deleted %s' % (username, path))
Example #11
0
 def _on_rename_buf(self, data):
     del self.paths_to_ids[data['old_path']]
     self.paths_to_ids[data['path']] = data['id']
     new = utils.get_full_path(data['path'])
     old = utils.get_full_path(data['old_path'])
     new_dir = os.path.split(new)[0]
     if new_dir:
         utils.mkdir(new_dir)
     view = self.get_view(data['id'])
     if view:
         view.rename(new)
     else:
         try:
             os.rename(old, new)
         except Exception as e:
             msg.debug('Error moving ', old, 'to', new, str_e(e))
             utils.save_buf(self.bufs[data.id])
     self.bufs[data['id']]['path'] = data['path']
 def _on_delete_buf(self, data):
     path = utils.get_full_path(data['path'])
     try:
         utils.rm(path)
     except Exception:
         pass
     user_id = data.get('user_id')
     username = self.get_username_by_id(user_id)
     msg.log('%s deleted %s' % (username, path))
Example #13
0
 def _on_rename_buf(self, data):
     del self.paths_to_ids[data['old_path']]
     self.paths_to_ids[data['path']] = data['id']
     new = utils.get_full_path(data['path'])
     old = utils.get_full_path(data['old_path'])
     new_dir = os.path.split(new)[0]
     if new_dir:
         utils.mkdir(new_dir)
     view = self.get_view(data['id'])
     if view:
         view.rename(new)
     else:
         try:
             os.rename(old, new)
         except Exception as e:
             msg.debug('Error moving ', old, 'to', new, str_e(e))
             utils.save_buf(self.bufs[data.id])
     self.bufs[data['id']]['path'] = data['path']
Example #14
0
    def _scan_dir(self, bufs, ig, read_only):
        changed_bufs = []
        missing_bufs = []
        new_files = set()

        if not read_only:
            new_files = set([utils.to_rel_path(x) for x in ig.list_paths()])

        for buf_id, buf in bufs.items():
            buf_id = int(buf_id)  # json keys must be strings
            buf_path = utils.get_full_path(buf['path'])
            new_dir = os.path.dirname(buf_path)
            utils.mkdir(new_dir)
            self.bufs[buf_id] = buf
            self.paths_to_ids[buf['path']] = buf_id

            view = self.get_view(buf_id)
            if view and not view.is_loading() and buf['encoding'] == 'utf8':
                view_text = view.get_text()
                view_md5 = hashlib.md5(view_text.encode('utf-8')).hexdigest()
                buf['buf'] = view_text
                buf['view'] = view
                G.VIEW_TO_HASH[view.native_id] = view_md5
                if view_md5 == buf['md5']:
                    msg.debug('md5 sum matches view. not getting buffer ', buf['path'])
                else:
                    changed_bufs.append(buf)
                    buf['md5'] = view_md5
                continue

            try:
                if buf['encoding'] == 'utf8':
                    if io:
                        buf_fd = io.open(buf_path, 'Urt', encoding='utf8')
                        buf_buf = buf_fd.read()
                    else:
                        buf_fd = open(buf_path, 'rb')
                        buf_buf = buf_fd.read().decode('utf-8').replace('\r\n', '\n')
                    md5 = hashlib.md5(buf_buf.encode('utf-8')).hexdigest()
                else:
                    buf_fd = open(buf_path, 'rb')
                    buf_buf = buf_fd.read()
                    md5 = hashlib.md5(buf_buf).hexdigest()
                buf_fd.close()
                buf['buf'] = buf_buf
                if md5 == buf['md5']:
                    msg.debug('md5 sum matches. not getting buffer ', buf['path'])
                else:
                    msg.debug('md5 differs. possibly getting buffer later ', buf['path'])
                    changed_bufs.append(buf)
                    buf['md5'] = md5
            except Exception as e:
                msg.debug('Error calculating md5 for ', buf['path'], ', ', str_e(e))
                missing_bufs.append(buf)
        return changed_bufs, missing_bufs, new_files
Example #15
0
    def _on_create_buf(self, data):
        if data['encoding'] == 'base64':
            data['buf'] = base64.b64decode(data['buf'])
        self.bufs[data['id']] = data
        self.paths_to_ids[data['path']] = data['id']
        abs_path = utils.get_full_path(data['path'])

        self.to_emacs('create_buf', {
            'full_path': utils.get_full_path(data['path']),
            'path': data['path'],
            'username': data.get('username', ''),
        })

        if abs_path not in self.emacs_handler.emacs_bufs:
            utils.save_buf(data)
            return
        text = self.emacs_handler.emacs_bufs.get(abs_path)[0]
        if text == data['buf']:
            return
        self.emacs_handler.bufs_changed.append(data['id'])
Example #16
0
 def _on_highlight(self, data):
     buf = self.bufs[data['id']]
     # TODO: save highlights for when user opens the buffer in emacs
     self.to_emacs('highlight', {
         'full_path': utils.get_full_path(buf['path']),
         'ranges': data['ranges'],
         'user_id': data['user_id'],
         'username': data.get('username', 'unknown user'),
         'following': data.get('following', False),
         'ping': data.get('ping', False)
     })
Example #17
0
 def _on_delete_buf(self, data):
     buf_id = int(data['id'])
     buf = self.bufs[buf_id]
     path = buf['path']
     try:
         super(AgentConnection, self)._on_delete_buf(data)
     except Exception as e:
         msg.debug('Unable to delete buf %s: %s' % (path, str(e)))
     else:
         self.to_emacs('delete_buf', {
             'full_path': utils.get_full_path(path),
             'path': path,
             'username': data.get('username', ''),
         })
Example #18
0
 def _on_delete_buf(self, data):
     buf_id = data['id']
     try:
         buf = self.bufs.get(buf_id)
         if buf:
             del self.paths_to_ids[buf['path']]
             del self.bufs[buf_id]
     except KeyError:
         msg.debug('KeyError deleting buf id ', buf_id)
     # TODO: if data['unlink'] == True, add to ignore?
     action = 'removed'
     path = utils.get_full_path(data['path'])
     if data.get('unlink', False):
         action = 'deleted'
         try:
             utils.rm(path)
         except Exception as e:
             msg.debug('Error deleting ', path, ': ', str_e(e))
     user_id = data.get('user_id')
     username = self.get_username_by_id(user_id)
     msg.log(username, ' ', action, ' ', path)
Example #19
0
 def _on_delete_buf(self, data):
     buf_id = data['id']
     try:
         buf = self.bufs.get(buf_id)
         if buf:
             del self.paths_to_ids[buf['path']]
             del self.bufs[buf_id]
     except KeyError:
         msg.debug('KeyError deleting buf id ', buf_id)
     # TODO: if data['unlink'] == True, add to ignore?
     action = 'removed'
     path = utils.get_full_path(data['path'])
     if data.get('unlink', False):
         action = 'deleted'
         try:
             utils.rm(path)
         except Exception as e:
             msg.debug('Error deleting ', path, ': ', str_e(e))
     user_id = data.get('user_id')
     username = self.get_username_by_id(user_id)
     msg.log(username, ' ', action, ' ', path)
Example #20
0
    def _rate_limited_upload(self, paths_iter, total_bytes, bytes_uploaded=0.0, upload_func=None):
        reactor.tick()
        upload_func = upload_func or (lambda x: self._upload(utils.get_full_path(x)))
        if len(self.proto) > 0:
            self.upload_timeout = utils.set_timeout(self._rate_limited_upload, 10, paths_iter, total_bytes, bytes_uploaded, upload_func)
            return

        bar_len = 20
        try:
            p = next(paths_iter)
            size = upload_func(p)
            bytes_uploaded += size
            try:
                percent = (bytes_uploaded / total_bytes)
            except ZeroDivisionError:
                percent = 0.5
            bar = '   |' + ('|' * int(bar_len * percent)) + (' ' * int((1 - percent) * bar_len)) + '|'
            editor.status_message('Uploading... %2.2f%% %s' % (percent * 100, bar))
        except StopIteration:
            editor.status_message('Uploading... 100% ' + ('|' * bar_len) + '| complete')
            msg.log('All done uploading')
            return
        self.upload_timeout = utils.set_timeout(self._rate_limited_upload, 50, paths_iter, total_bytes, bytes_uploaded, upload_func)
Example #21
0
    def _rate_limited_upload(self, paths_iter, total_bytes, bytes_uploaded=0.0, upload_func=None):
        reactor.tick()
        upload_func = upload_func or (lambda x: self._upload(utils.get_full_path(x)))
        if len(self.proto) > 0:
            self.upload_timeout = utils.set_timeout(self._rate_limited_upload, 10, paths_iter, total_bytes, bytes_uploaded, upload_func)
            return

        bar_len = 20
        try:
            p = next(paths_iter)
            size = upload_func(p)
            bytes_uploaded += size
            try:
                percent = (bytes_uploaded / total_bytes)
            except ZeroDivisionError:
                percent = 0.5
            bar = '   |' + ('|' * int(bar_len * percent)) + (' ' * int((1 - percent) * bar_len)) + '|'
            editor.status_message('Uploading... %2.2f%% %s' % (percent * 100, bar))
        except StopIteration:
            editor.status_message('Uploading... 100% ' + ('|' * bar_len) + '| complete')
            msg.log('All done uploading')
            return
        self.upload_timeout = utils.set_timeout(self._rate_limited_upload, 50, paths_iter, total_bytes, bytes_uploaded, upload_func)
Example #22
0
 def __upload_buf(buf):
     return self._upload(utils.get_full_path(buf['path']),
                         buf.get('buf'))
Example #23
0
    def _on_room_info(self, data):
        self.reset()
        self.joined_workspace = True
        self.workspace_info = data
        G.PERMS = data['perms']

        if 'patch' not in data['perms']:
            no_perms_msg = '''You don't have permission to edit this workspace. All files will be read-only.'''
            msg.log('No patch permission. Setting buffers to read-only')
            if 'request_perm' in data['perms']:
                should_send = yield self.ok_cancel_dialog, no_perms_msg + '\nDo you want to request edit permission?'
                if should_send:
                    self.send({
                        'name': 'request_perms',
                        'perms': ['edit_room']
                    })
            else:
                editor.error_message(no_perms_msg)

        floo_json = {
            'url':
            utils.to_workspace_url({
                'owner': self.owner,
                'workspace': self.workspace,
                'host': self.proto.host,
                'port': self.proto.port,
                'secure': self.proto.secure,
            })
        }
        utils.update_floo_file(os.path.join(G.PROJECT_PATH, '.floo'),
                               floo_json)

        changed_bufs = []
        missing_bufs = []
        for buf_id, buf in data['bufs'].items():
            buf_id = int(buf_id)  # json keys must be strings
            buf_path = utils.get_full_path(buf['path'])
            new_dir = os.path.dirname(buf_path)
            utils.mkdir(new_dir)
            self.bufs[buf_id] = buf
            self.paths_to_ids[buf['path']] = buf_id

            view = self.get_view(buf_id)
            if view and not view.is_loading() and buf['encoding'] == 'utf8':
                view_text = view.get_text()
                view_md5 = hashlib.md5(view_text.encode('utf-8')).hexdigest()
                buf['buf'] = view_text
                buf['view'] = view
                G.VIEW_TO_HASH[view.native_id] = view_md5
                if view_md5 == buf['md5']:
                    msg.debug('md5 sum matches view. not getting buffer %s' %
                              buf['path'])
                else:
                    changed_bufs.append(buf_id)
                    buf['md5'] = view_md5
            else:
                try:
                    if buf['encoding'] == "utf8":
                        if io:
                            buf_fd = io.open(buf_path, 'Urt', encoding='utf8')
                            buf_buf = buf_fd.read()
                        else:
                            buf_fd = open(buf_path, 'rb')
                            buf_buf = buf_fd.read().decode('utf-8').replace(
                                '\r\n', '\n')
                        md5 = hashlib.md5(buf_buf.encode('utf-8')).hexdigest()
                    else:
                        buf_fd = open(buf_path, 'rb')
                        buf_buf = buf_fd.read()
                        md5 = hashlib.md5(buf_buf).hexdigest()
                    buf_fd.close()
                    buf['buf'] = buf_buf
                    if md5 == buf['md5']:
                        msg.debug('md5 sum matches. not getting buffer %s' %
                                  buf['path'])
                    else:
                        msg.debug(
                            'md5 differs. possibly getting buffer later %s' %
                            buf['path'])
                        changed_bufs.append(buf_id)
                        buf['md5'] = md5
                except Exception as e:
                    msg.debug('Error calculating md5 for %s, %s' %
                              (buf['path'], e))
                    missing_bufs.append(buf_id)

        stomp_local = self.should_get_bufs
        if stomp_local and (changed_bufs or missing_bufs):
            changed = [self.bufs[buf_id] for buf_id in changed_bufs]
            missing = [self.bufs[buf_id] for buf_id in missing_bufs]
            choice = yield self.stomp_prompt, changed, missing
            if choice not in [0, 1]:
                self.stop()
                return
            stomp_local = bool(choice)

        for buf_id in changed_bufs:
            buf = self.bufs[buf_id]
            if stomp_local:
                self.get_buf(buf_id, buf.get('view'))
                self.save_on_get_bufs.add(buf_id)
            else:
                self._upload(utils.get_full_path(buf['path']), buf['buf'])

        for buf_id in missing_bufs:
            buf = self.bufs[buf_id]
            if stomp_local:
                self.get_buf(buf_id, buf.get('view'))
                self.save_on_get_bufs.add(buf_id)
            else:
                self.send({
                    'name': 'delete_buf',
                    'id': buf['id'],
                })

        success_msg = 'Successfully joined workspace %s/%s' % (self.owner,
                                                               self.workspace)
        msg.log(success_msg)
        editor.status_message(success_msg)

        temp_data = data.get('temp_data', {})
        hangout = temp_data.get('hangout', {})
        hangout_url = hangout.get('url')
        if hangout_url:
            self.prompt_join_hangout(hangout_url)

        data = utils.get_persistent_data()
        data['recent_workspaces'].insert(0, {"url": self.workspace_url})
        utils.update_persistent_data(data)
        utils.add_workspace_to_persistent_json(self.owner, self.workspace,
                                               self.workspace_url,
                                               G.PROJECT_PATH)
        self.emit("room_info")
Example #24
0
    def _on_room_info(self, data):
        self.reset()
        G.JOINED_WORKSPACE = True
        self.workspace_info = data
        G.PERMS = data['perms']

        if 'patch' not in data['perms']:
            msg.log('No patch permission. Setting buffers to read-only')
            should_send = yield self.ok_cancel_dialog, 'You don\'t have permission to edit this workspace. All files will be read-only.\n\nDo you want to request edit permission?'
            if should_send:
                self.send({'name': 'request_perms', 'perms': ['edit_room']})

        floo_json = {
            'url': utils.to_workspace_url({
                'owner': self.owner,
                'workspace': self.workspace,
                'host': self.proto.host,
                'port': self.proto.port,
                'secure': self.proto.secure,
            })
        }
        utils.update_floo_file(os.path.join(G.PROJECT_PATH, '.floo'), floo_json)

        changed_bufs = []
        missing_bufs = []
        for buf_id, buf in data['bufs'].items():
            buf_id = int(buf_id)  # json keys must be strings
            buf_path = utils.get_full_path(buf['path'])
            new_dir = os.path.dirname(buf_path)
            utils.mkdir(new_dir)
            self.bufs[buf_id] = buf
            self.paths_to_ids[buf['path']] = buf_id

            view = self.get_view(buf_id)
            if view and not view.is_loading() and buf['encoding'] == 'utf8':
                view_text = view.get_text()
                view_md5 = hashlib.md5(view_text.encode('utf-8')).hexdigest()
                if view_md5 == buf['md5']:
                    msg.debug('md5 sum matches view. not getting buffer %s' % buf['path'])
                    buf['buf'] = view_text
                    G.VIEW_TO_HASH[view.native_id] = view_md5
                elif self.should_get_bufs:
                    changed_bufs.append(buf_id)
            else:
                try:
                    buf_fd = open(buf_path, 'rb')
                    buf_buf = buf_fd.read()
                    md5 = hashlib.md5(buf_buf).hexdigest()
                    if md5 == buf['md5']:
                        msg.debug('md5 sum matches. not getting buffer %s' % buf['path'])
                        if buf['encoding'] == 'utf8':
                            buf_buf = buf_buf.decode('utf-8')
                        buf['buf'] = buf_buf
                    elif self.should_get_bufs:
                        changed_bufs.append(buf_id)
                except Exception as e:
                    msg.debug('Error calculating md5:', e)
                    missing_bufs.append(buf_id)

        if changed_bufs and self.should_get_bufs:
            if len(changed_bufs) > 4:
                prompt = '%s local files are different from the workspace. Overwrite your local files?' % len(changed_bufs)
            else:
                prompt = 'Overwrite the following local files?\n'
                for buf_id in changed_bufs:
                    prompt += '\n%s' % self.bufs[buf_id]['path']

            stomp_local = yield self.ok_cancel_dialog, prompt
            for buf_id in changed_bufs:
                if stomp_local:
                    self.get_buf(buf_id)
                    self.save_on_get_bufs.add(buf_id)
                else:
                    buf = self.bufs[buf_id]
                    # TODO: this is inefficient. we just read the file 20 lines ago
                    self.upload(utils.get_full_path(buf['path']))

        for buf_id in missing_bufs:
            self.get_buf(buf_id)

        success_msg = 'Successfully joined workspace %s/%s' % (self.owner, self.workspace)
        msg.log(success_msg)
        editor.status_message(success_msg)

        temp_data = data.get('temp_data', {})
        hangout = temp_data.get('hangout', {})
        hangout_url = hangout.get('url')
        if hangout_url:
            self.prompt_join_hangout(hangout_url)

        data = utils.get_persistent_data()
        data['recent_workspaces'].insert(0, {"url": self.workspace_url})
        utils.update_persistent_data(data)
        utils.add_workspace_to_persistent_json(self.owner, self.workspace, self.workspace_url, G.PROJECT_PATH)
        self.emit("room_info")
Example #25
0
 def _upload_file_by_path(self, rel_path):
     return self._upload(utils.get_full_path(rel_path), self.get_view_text_by_path(rel_path))
Example #26
0
    def _on_room_info(self, data):
        self.reset()
        self.joined_workspace = True
        self.workspace_info = data
        G.PERMS = data['perms']

        self.proto.reset_retries()

        if G.OUTBOUND_FILTERING:
            msg.error('Detected outbound port blocking! See https://floobits.com/help/network for more info.')

        read_only = False
        if 'patch' not in data['perms']:
            read_only = True
            no_perms_msg = '''You don't have permission to edit this workspace. All files will be read-only.'''
            msg.log('No patch permission. Setting buffers to read-only')
            if 'request_perm' in data['perms']:
                should_send = yield self.ok_cancel_dialog, no_perms_msg + '\nDo you want to request edit permission?'
                # TODO: wait for perms to be OK'd/denied before uploading or bailing
                if should_send:
                    self.send({'name': 'request_perms', 'perms': ['edit_room']})
            else:
                if G.EXPERT_MODE:
                    editor.status_message(no_perms_msg)
                else:
                    editor.error_message(no_perms_msg)

        floo_json = {
            'url': utils.to_workspace_url({
                'owner': self.owner,
                'workspace': self.workspace,
                'host': self.proto.host,
                'port': self.proto.port,
                'secure': self.proto.secure,
            })
        }
        utils.update_floo_file(os.path.join(G.PROJECT_PATH, '.floo'), floo_json)
        utils.update_recent_workspaces(self.workspace_url)

        changed_bufs = []
        missing_bufs = []
        new_files = set()
        ig = ignore.create_ignore_tree(G.PROJECT_PATH)
        G.IGNORE = ig
        if not read_only:
            new_files = set([utils.to_rel_path(x) for x in ig.list_paths()])

        for buf_id, buf in data['bufs'].items():
            buf_id = int(buf_id)  # json keys must be strings
            buf_path = utils.get_full_path(buf['path'])
            new_dir = os.path.dirname(buf_path)
            utils.mkdir(new_dir)
            self.bufs[buf_id] = buf
            self.paths_to_ids[buf['path']] = buf_id

            view = self.get_view(buf_id)
            if view and not view.is_loading() and buf['encoding'] == 'utf8':
                view_text = view.get_text()
                view_md5 = hashlib.md5(view_text.encode('utf-8')).hexdigest()
                buf['buf'] = view_text
                buf['view'] = view
                G.VIEW_TO_HASH[view.native_id] = view_md5
                if view_md5 == buf['md5']:
                    msg.debug('md5 sum matches view. not getting buffer ', buf['path'])
                else:
                    changed_bufs.append(buf)
                    buf['md5'] = view_md5
                continue

            try:
                if buf['encoding'] == 'utf8':
                    if io:
                        buf_fd = io.open(buf_path, 'Urt', encoding='utf8')
                        buf_buf = buf_fd.read()
                    else:
                        buf_fd = open(buf_path, 'rb')
                        buf_buf = buf_fd.read().decode('utf-8').replace('\r\n', '\n')
                    md5 = hashlib.md5(buf_buf.encode('utf-8')).hexdigest()
                else:
                    buf_fd = open(buf_path, 'rb')
                    buf_buf = buf_fd.read()
                    md5 = hashlib.md5(buf_buf).hexdigest()
                buf_fd.close()
                buf['buf'] = buf_buf
                if md5 == buf['md5']:
                    msg.debug('md5 sum matches. not getting buffer ', buf['path'])
                else:
                    msg.debug('md5 differs. possibly getting buffer later ', buf['path'])
                    changed_bufs.append(buf)
                    buf['md5'] = md5
            except Exception as e:
                msg.debug('Error calculating md5 for ', buf['path'], ', ', str_e(e))
                missing_bufs.append(buf)

        ignored = []
        for p, buf_id in self.paths_to_ids.items():
            if p not in new_files:
                ignored.append(p)
            new_files.discard(p)

        if self.action == utils.JOIN_ACTION.UPLOAD:
            yield self._initial_upload, ig, missing_bufs, changed_bufs
            # TODO: maybe use org name here
            who = 'Your friends'
            anon_perms = G.AGENT.workspace_info.get('anon_perms')
            if 'get_buf' in anon_perms:
                who = 'Anyone'
            _msg = 'You are sharing:\n\n%s\n\n%s can join your workspace at:\n\n%s' % (G.PROJECT_PATH, who, G.AGENT.workspace_url)
            # Workaround for horrible Sublime Text bug
            utils.set_timeout(editor.message_dialog, 0, _msg)
        elif changed_bufs or missing_bufs or new_files:
            # TODO: handle readonly here
            if self.action == utils.JOIN_ACTION.PROMPT:
                stomp_local = yield self.stomp_prompt, changed_bufs, missing_bufs, list(new_files), ignored
                if stomp_local not in [0, 1]:
                    self.stop()
                    return
            elif self.action == utils.JOIN_ACTION.DOWNLOAD:
                stomp_local = True
            else:
                # This should never happen
                assert False
                return

            if stomp_local:
                for buf in changed_bufs:
                    self.get_buf(buf['id'], buf.get('view'))
                    self.save_on_get_bufs.add(buf['id'])
                for buf in missing_bufs:
                    self.get_buf(buf['id'], buf.get('view'))
                    self.save_on_get_bufs.add(buf['id'])
            else:
                yield self._initial_upload, ig, missing_bufs, changed_bufs

        success_msg = 'Successfully joined workspace %s/%s' % (self.owner, self.workspace)
        msg.log(success_msg)
        editor.status_message(success_msg)

        data = utils.get_persistent_data()
        data['recent_workspaces'].insert(0, {"url": self.workspace_url})
        utils.update_persistent_data(data)
        utils.add_workspace_to_persistent_json(self.owner, self.workspace, self.workspace_url, G.PROJECT_PATH)

        temp_data = data.get('temp_data', {})
        hangout = temp_data.get('hangout', {})
        hangout_url = hangout.get('url')
        if hangout_url:
            self.prompt_join_hangout(hangout_url)

        self.emit("room_info")
Example #27
0
 def _upload_file_by_path(self, rel_path):
     return self._upload(utils.get_full_path(rel_path),
                         self.get_view_text_by_path(rel_path))
Example #28
0
 def __upload_buf(buf):
     return self._upload(utils.get_full_path(buf['path']), buf.get('buf'))
    def _on_room_info(self, data):
        self.reset()
        self.joined_workspace = True
        self.workspace_info = data
        G.PERMS = data['perms']

        if 'patch' not in data['perms']:
            no_perms_msg = '''You don't have permission to edit this workspace. All files will be read-only.'''
            msg.log('No patch permission. Setting buffers to read-only')
            if 'request_perm' in data['perms']:
                should_send = yield self.ok_cancel_dialog, no_perms_msg + '\nDo you want to request edit permission?'
                if should_send:
                    self.send({'name': 'request_perms', 'perms': ['edit_room']})
            else:
                editor.error_message(no_perms_msg)

        floo_json = {
            'url': utils.to_workspace_url({
                'owner': self.owner,
                'workspace': self.workspace,
                'host': self.proto.host,
                'port': self.proto.port,
                'secure': self.proto.secure,
            })
        }
        utils.update_floo_file(os.path.join(G.PROJECT_PATH, '.floo'), floo_json)

        changed_bufs = []
        missing_bufs = []
        for buf_id, buf in data['bufs'].items():
            buf_id = int(buf_id)  # json keys must be strings
            buf_path = utils.get_full_path(buf['path'])
            new_dir = os.path.dirname(buf_path)
            utils.mkdir(new_dir)
            self.bufs[buf_id] = buf
            self.paths_to_ids[buf['path']] = buf_id

            view = self.get_view(buf_id)
            if view and not view.is_loading() and buf['encoding'] == 'utf8':
                view_text = view.get_text()
                view_md5 = hashlib.md5(view_text.encode('utf-8')).hexdigest()
                buf['buf'] = view_text
                buf['view'] = view
                G.VIEW_TO_HASH[view.native_id] = view_md5
                if view_md5 == buf['md5']:
                    msg.debug('md5 sum matches view. not getting buffer %s' % buf['path'])
                else:
                    changed_bufs.append(buf_id)
                    buf['md5'] = view_md5
            else:
                try:
                    if buf['encoding'] == "utf8":
                        if io:
                            buf_fd = io.open(buf_path, 'Urt', encoding='utf8')
                            buf_buf = buf_fd.read()
                        else:
                            buf_fd = open(buf_path, 'rb')
                            buf_buf = buf_fd.read().decode('utf-8').replace('\r\n', '\n')
                        md5 = hashlib.md5(buf_buf.encode('utf-8')).hexdigest()
                    else:
                        buf_fd = open(buf_path, 'rb')
                        buf_buf = buf_fd.read()
                        md5 = hashlib.md5(buf_buf).hexdigest()
                    buf_fd.close()
                    buf['buf'] = buf_buf
                    if md5 == buf['md5']:
                        msg.debug('md5 sum matches. not getting buffer %s' % buf['path'])
                    else:
                        msg.debug('md5 differs. possibly getting buffer later %s' % buf['path'])
                        changed_bufs.append(buf_id)
                        buf['md5'] = md5
                except Exception as e:
                    msg.debug('Error calculating md5 for %s, %s' % (buf['path'], e))
                    missing_bufs.append(buf_id)

        stomp_local = self.should_get_bufs
        if stomp_local and (changed_bufs or missing_bufs):
            changed = [self.bufs[buf_id] for buf_id in changed_bufs]
            missing = [self.bufs[buf_id] for buf_id in missing_bufs]
            choice = yield self.stomp_prompt, changed, missing
            if choice not in [0, 1]:
                self.stop()
                return
            stomp_local = bool(choice)

        for buf_id in changed_bufs:
            buf = self.bufs[buf_id]
            if stomp_local:
                self.get_buf(buf_id, buf.get('view'))
                self.save_on_get_bufs.add(buf_id)
            else:
                self._upload(utils.get_full_path(buf['path']), buf['buf'])

        for buf_id in missing_bufs:
            buf = self.bufs[buf_id]
            if stomp_local:
                self.get_buf(buf_id, buf.get('view'))
                self.save_on_get_bufs.add(buf_id)
            else:
                self.send({
                    'name': 'delete_buf',
                    'id': buf['id'],
                })

        success_msg = 'Successfully joined workspace %s/%s' % (self.owner, self.workspace)
        msg.log(success_msg)
        editor.status_message(success_msg)

        temp_data = data.get('temp_data', {})
        hangout = temp_data.get('hangout', {})
        hangout_url = hangout.get('url')
        if hangout_url:
            self.prompt_join_hangout(hangout_url)

        data = utils.get_persistent_data()
        data['recent_workspaces'].insert(0, {"url": self.workspace_url})
        utils.update_persistent_data(data)
        utils.add_workspace_to_persistent_json(self.owner, self.workspace, self.workspace_url, G.PROJECT_PATH)
        self.emit("room_info")
Example #30
0
    def _scan_dir(self, bufs, ig, read_only):
        status_msg = 'Comparing local files against workspace...'
        editor.status_message(status_msg)
        update_status_msg = getattr(self, 'update_status_msg', None)
        if update_status_msg:
            try:
                update_status_msg(self, status_msg)
            except Exception as e:
                pass

        changed_bufs = []
        missing_bufs = []
        new_files = set()

        if not read_only:
            new_files = set([utils.to_rel_path(x) for x in ig.list_paths()])

        for buf_id, buf in bufs.items():
            buf_id = int(buf_id)  # json keys must be strings
            buf_path = utils.get_full_path(buf['path'])
            view = self.get_view(buf_id)
            if view and not view.is_loading() and buf['encoding'] == 'utf8':
                view_text = view.get_text()
                view_md5 = hashlib.md5(view_text.encode('utf-8')).hexdigest()
                buf['buf'] = view_text
                buf['view'] = view
                G.VIEW_TO_HASH[view.native_id] = view_md5
                if view_md5 == buf['md5']:
                    msg.debug('md5 sum matches view. not getting buffer ',
                              buf['path'])
                else:
                    changed_bufs.append(buf)
                    buf['md5'] = view_md5
                continue

            try:
                if buf['encoding'] == 'utf8':
                    if io:
                        buf_fd = io.open(buf_path, 'Urt', encoding='utf8')
                        buf_buf = buf_fd.read()
                    else:
                        buf_fd = open(buf_path, 'rb')
                        buf_buf = buf_fd.read().decode('utf-8').replace(
                            '\r\n', '\n')
                    md5 = hashlib.md5(buf_buf.encode('utf-8')).hexdigest()
                else:
                    buf_fd = open(buf_path, 'rb')
                    buf_buf = buf_fd.read()
                    md5 = hashlib.md5(buf_buf).hexdigest()
                buf_fd.close()
                buf['buf'] = buf_buf
                if md5 == buf['md5']:
                    msg.debug('md5 sum matches. not getting buffer ',
                              buf['path'])
                else:
                    msg.debug('md5 differs. possibly getting buffer later ',
                              buf['path'])
                    changed_bufs.append(buf)
                    buf['md5'] = md5
            except Exception as e:
                msg.debug('Error calculating md5 for ', buf['path'], ', ',
                          str_e(e))
                missing_bufs.append(buf)
        editor.status_message(
            'Comparing local files against workspace... done.')
        return changed_bufs, missing_bufs, new_files
    def _on_room_info(self, data):
        self.reset()
        G.JOINED_WORKSPACE = True
        self.workspace_info = data
        G.PERMS = data['perms']

        if 'patch' not in data['perms']:
            msg.log('No patch permission. Setting buffers to read-only')
            should_send = yield self.ok_cancel_dialog, '''You don't have permission to edit this workspace. All files will be read-only.
Do you want to request edit permission?'''
            if should_send:
                self.send({'name': 'request_perms', 'perms': ['edit_room']})

        floo_json = {
            'url': utils.to_workspace_url({
                'owner': self.owner,
                'workspace': self.workspace,
                'host': self.proto.host,
                'port': self.proto.port,
                'secure': self.proto.secure,
            })
        }
        utils.update_floo_file(os.path.join(G.PROJECT_PATH, '.floo'), floo_json)

        changed_bufs = []
        missing_bufs = []
        for buf_id, buf in data['bufs'].items():
            buf_id = int(buf_id)  # json keys must be strings
            buf_path = utils.get_full_path(buf['path'])
            new_dir = os.path.dirname(buf_path)
            utils.mkdir(new_dir)
            self.bufs[buf_id] = buf
            self.paths_to_ids[buf['path']] = buf_id

            view = self.get_view(buf_id)
            if view and not view.is_loading() and buf['encoding'] == 'utf8':
                view_text = view.get_text()
                view_md5 = hashlib.md5(view_text.encode('utf-8')).hexdigest()
                if view_md5 == buf['md5']:
                    msg.debug('md5 sum matches view. not getting buffer %s' % buf['path'])
                    buf['buf'] = view_text
                    G.VIEW_TO_HASH[view.native_id] = view_md5
                elif self.should_get_bufs:
                    changed_bufs.append(buf_id)
            else:
                try:
                    buf_fd = open(buf_path, 'rb')
                    buf_buf = buf_fd.read()
                    md5 = hashlib.md5(buf_buf).hexdigest()
                    if md5 == buf['md5']:
                        msg.debug('md5 sum matches. not getting buffer %s' % buf['path'])
                        if buf['encoding'] == 'utf8':
                            buf_buf = buf_buf.decode('utf-8')
                        buf['buf'] = buf_buf
                    elif self.should_get_bufs:
                        changed_bufs.append(buf_id)
                except Exception as e:
                    msg.debug('Error calculating md5:', e)
                    missing_bufs.append(buf_id)

        if changed_bufs and self.should_get_bufs:
            if len(changed_bufs) > 4:
                prompt = '%s local files are different from the workspace. Overwrite your local files?' % len(changed_bufs)
            else:
                prompt = 'Overwrite the following local files?\n'
                for buf_id in changed_bufs:
                    prompt += '\n%s' % self.bufs[buf_id]['path']

            stomp_local = yield self.ok_cancel_dialog, prompt
            for buf_id in changed_bufs:
                if stomp_local:
                    self.get_buf(buf_id)
                    self.save_on_get_bufs.add(buf_id)
                else:
                    buf = self.bufs[buf_id]
                    # TODO: this is inefficient. we just read the file 20 lines ago
                    self.upload(utils.get_full_path(buf['path']))

        for buf_id in missing_bufs:
            self.get_buf(buf_id)

        success_msg = 'Successfully joined workspace %s/%s' % (self.owner, self.workspace)
        msg.log(success_msg)
        editor.status_message(success_msg)

        temp_data = data.get('temp_data', {})
        hangout = temp_data.get('hangout', {})
        hangout_url = hangout.get('url')
        if hangout_url:
            self.prompt_join_hangout(hangout_url)

        data = utils.get_persistent_data()
        data['recent_workspaces'].insert(0, {"url": self.workspace_url})
        utils.update_persistent_data(data)
        utils.add_workspace_to_persistent_json(self.owner, self.workspace, self.workspace_url, G.PROJECT_PATH)
        self.emit("room_info")
Example #32
0
    def _on_room_info(self, data):
        self.joined_workspace = True
        self.workspace_info = data
        G.PERMS = data['perms']

        self.proto.reset_retries()

        if G.OUTBOUND_FILTERING:
            msg.error(
                'Detected outbound port blocking! See https://floobits.com/help/network for more info.'
            )

        read_only = False
        if 'patch' not in data['perms']:
            read_only = True
            no_perms_msg = '''You don't have permission to edit this workspace. All files will be read-only.'''
            msg.log('No patch permission. Setting buffers to read-only')
            if 'request_perm' in data['perms']:
                should_send = yield self.ok_cancel_dialog, no_perms_msg + '\nDo you want to request edit permission?'
                # TODO: wait for perms to be OK'd/denied before uploading or bailing
                if should_send:
                    self.send({
                        'name': 'request_perms',
                        'perms': ['edit_room']
                    })
            else:
                if G.EXPERT_MODE:
                    editor.status_message(no_perms_msg)
                else:
                    editor.error_message(no_perms_msg)

        floo_json = {
            'url':
            utils.to_workspace_url({
                'owner': self.owner,
                'workspace': self.workspace,
                'host': self.proto.host,
                'port': self.proto.port,
                'secure': self.proto.secure,
            })
        }
        utils.update_floo_file(os.path.join(G.PROJECT_PATH, '.floo'),
                               floo_json)
        utils.update_recent_workspaces(self.workspace_url)

        changed_bufs = []
        missing_bufs = []
        new_files = set()
        ig = ignore.create_ignore_tree(G.PROJECT_PATH)
        G.IGNORE = ig
        if not read_only:
            new_files = set([utils.to_rel_path(x) for x in ig.list_paths()])

        for buf_id, buf in data['bufs'].items():
            buf_id = int(buf_id)  # json keys must be strings
            buf_path = utils.get_full_path(buf['path'])
            new_dir = os.path.dirname(buf_path)
            utils.mkdir(new_dir)
            self.bufs[buf_id] = buf
            self.paths_to_ids[buf['path']] = buf_id

            view = self.get_view(buf_id)
            if view and not view.is_loading() and buf['encoding'] == 'utf8':
                view_text = view.get_text()
                view_md5 = hashlib.md5(view_text.encode('utf-8')).hexdigest()
                buf['buf'] = view_text
                buf['view'] = view
                G.VIEW_TO_HASH[view.native_id] = view_md5
                if view_md5 == buf['md5']:
                    msg.debug('md5 sum matches view. not getting buffer ',
                              buf['path'])
                else:
                    changed_bufs.append(buf)
                    buf['md5'] = view_md5
                continue

            try:
                if buf['encoding'] == 'utf8':
                    if io:
                        buf_fd = io.open(buf_path, 'Urt', encoding='utf8')
                        buf_buf = buf_fd.read()
                    else:
                        buf_fd = open(buf_path, 'rb')
                        buf_buf = buf_fd.read().decode('utf-8').replace(
                            '\r\n', '\n')
                    md5 = hashlib.md5(buf_buf.encode('utf-8')).hexdigest()
                else:
                    buf_fd = open(buf_path, 'rb')
                    buf_buf = buf_fd.read()
                    md5 = hashlib.md5(buf_buf).hexdigest()
                buf_fd.close()
                buf['buf'] = buf_buf
                if md5 == buf['md5']:
                    msg.debug('md5 sum matches. not getting buffer ',
                              buf['path'])
                else:
                    msg.debug('md5 differs. possibly getting buffer later ',
                              buf['path'])
                    changed_bufs.append(buf)
                    buf['md5'] = md5
            except Exception as e:
                msg.debug('Error calculating md5 for ', buf['path'], ', ',
                          str_e(e))
                missing_bufs.append(buf)

        ignored = []
        for p, buf_id in self.paths_to_ids.items():
            if p not in new_files:
                ignored.append(p)
            new_files.discard(p)

        if self.action == utils.JOIN_ACTION.UPLOAD:
            yield self._initial_upload, ig, missing_bufs, changed_bufs
            # TODO: maybe use org name here
            who = 'Your friends'
            anon_perms = G.AGENT.workspace_info.get('anon_perms')
            if 'get_buf' in anon_perms:
                who = 'Anyone'
            _msg = 'You are sharing:\n\n%s\n\n%s can join your workspace at:\n\n%s' % (
                G.PROJECT_PATH, who, G.AGENT.workspace_url)
            # Workaround for horrible Sublime Text bug
            utils.set_timeout(editor.message_dialog, 0, _msg)
        elif changed_bufs or missing_bufs or new_files:
            # TODO: handle readonly here
            if self.action == utils.JOIN_ACTION.PROMPT:
                stomp_local = yield self.stomp_prompt, changed_bufs, missing_bufs, list(
                    new_files), ignored
                if stomp_local not in [0, 1]:
                    self.stop()
                    return
            elif self.action == utils.JOIN_ACTION.DOWNLOAD:
                stomp_local = True
            else:
                # This should never happen
                assert False
                return

            if stomp_local:
                for buf in changed_bufs:
                    self.get_buf(buf['id'], buf.get('view'))
                    self.save_on_get_bufs.add(buf['id'])
                for buf in missing_bufs:
                    self.get_buf(buf['id'], buf.get('view'))
                    self.save_on_get_bufs.add(buf['id'])
            else:
                yield self._initial_upload, ig, missing_bufs, changed_bufs

        success_msg = '%s@%s/%s: Joined!' % (self.username, self.owner,
                                             self.workspace)
        msg.log(success_msg)
        editor.status_message(success_msg)

        data = utils.get_persistent_data()
        data['recent_workspaces'].insert(0, {"url": self.workspace_url})
        utils.update_persistent_data(data)
        utils.add_workspace_to_persistent_json(self.owner, self.workspace,
                                               self.workspace_url,
                                               G.PROJECT_PATH)

        temp_data = data.get('temp_data', {})
        hangout = temp_data.get('hangout', {})
        hangout_url = hangout.get('url')
        if hangout_url:
            self.prompt_join_hangout(hangout_url)

        self.emit("room_info")