예제 #1
0
    def test_chain_with_resolved(self):
        def worker(resolve_fn):
            resolve_fn(999)

        def assertResult(result):
            self.assertEqual(result, 999)

        promise = Promise(worker)
        self.assertTrue(promise._is_resolved())
        promise2 = promise.then(assertResult)
        self.assertTrue(promise2._is_resolved())
예제 #2
0
    def test_chain_with_pending(self):
        def worker_async(resolve_fn):
            sublime.set_timeout_async(lambda: resolve_fn(999), 100)

        def assertResult(result):
            self.assertEqual(result, 999)

        promise = Promise(worker_async)
        self.assertFalse(promise._is_resolved())
        promise2 = promise.then(assertResult)
        self.assertFalse(promise2._is_resolved())
        # Let promises resolve.
        time.sleep(0.2)
        self.assertTrue(promise._is_resolved())
예제 #3
0
    def git_current_branch(self):
        """Query the current branch of the file's repository."""
        if self._git_branch:
            return Promise.resolve(self._git_branch)

        def cache_result(branch):
            self._git_branch = branch
            return branch

        args = [settings.git_binary_path, 'rev-parse', '--abbrev-ref', 'HEAD']
        return self.run_command(args).then(cache_result)
예제 #4
0
    def test_chain_with_promise(self):
        def worker_async(resolve_fn):
            sublime.set_timeout_async(lambda: resolve_fn(999), 100)

        def worker_async2(resolve_fn):
            sublime.set_timeout_async(lambda: resolve_fn(888), 100)

        def callback(async_value):
            self.assertEqual(async_value, 999)
            return Promise(worker_async2)

        def verify_async2_value(value):
            self.assertEqual(value, 888)

        promise = Promise(worker_async)
        self.assertFalse(promise._is_resolved())
        promise2 = promise.then(callback)
        self.assertFalse(promise2._is_resolved())
        promise2.then(verify_async2_value)
        # Let both promises resolve.
        time.sleep(0.500)
        self.assertTrue(promise._is_resolved())
        self.assertEqual(promise._get_value(), 999)
        self.assertTrue(promise2._is_resolved())
        self.assertEqual(promise2._get_value(), 888)
예제 #5
0
    def run_command(self, args, decode=True):
        """Run a git command asynchronously and return a Promise.

        Arguments:
            args    - a list of arguments used to create the git subprocess.
            decode  - if True the git's output is decoded assuming utf-8
                      which is the default output encoding of git.
        """
        def read_output(resolve):
            """Start git process and forward its output to the Resolver."""
            stdout, stderr = None, None

            try:
                if os.name == 'nt':
                    startupinfo = subprocess.STARTUPINFO()
                    startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
                else:
                    startupinfo = None
                proc = subprocess.Popen(args=args,
                                        cwd=self._git_tree,
                                        startupinfo=startupinfo,
                                        stdout=subprocess.PIPE,
                                        stderr=subprocess.PIPE,
                                        stdin=subprocess.PIPE)
                if _HAVE_TIMEOUT:
                    stdout, stderr = proc.communicate(timeout=30)
                else:
                    stdout, stderr = proc.communicate()
            except OSError as error:
                # print out system error message
                print('GitGutter: \'git %s\' failed with \"%s\"' %
                      (args[1], error))
            except TimeoutExpired:
                proc.kill()
                stdout, stderr = proc.communicate()
            finally:
                if stderr and stderr.startswith(b'fatal:'):
                    # print out git's error message
                    print('GitGutter: \'git %s\' failed with \"%s\"' %
                          (args[1], stderr.decode('utf-8').strip()))
                if stdout and decode:
                    # resolve with string value
                    resolve(stdout.decode('utf-8').strip())
                else:
                    # resolve with binary value
                    resolve(stdout)

        def run_async(resolve):
            set_timeout(lambda: read_output(resolve), 10)

        return Promise(run_async)
예제 #6
0
        def check_commit(commit):
            """Check if compare target changed and update git file then.

            If the commit has didn't change since the last run, the temporary
            file is still up to date and git 'show' can be skipped and the
            promise is resolved with False.

            This method uses `git archive` to read the file content from git
            repository to enable support of smudge filters (fixes Issue #74).
            Git applies those smudge filters to some commands like `archive`,
            `diff` and `checkout` only, but not to commands like `show`.

            Arguments:
                commit (string): full hash of the commit the view is currently
                                 compared against.
            Returns:
                bool: True if temporary file was updated, False otherwise.
            """
            def write_file(contents):
                """Extract output and write it to a temporary file.

                The function resolves the promise with True to indicate the
                updated git file.
                """
                try:
                    # Mangle end of lines
                    contents = contents.replace(b'\r\n', b'\n')
                    contents = contents.replace(b'\r', b'\n')
                    # Write the content to file
                    if not self._git_temp_file:
                        self._git_temp_file = self.tmp_file()
                    with open(self._git_temp_file, 'wb') as file:
                        file.write(contents)
                    self.git_tracked = True
                    self._git_compared_commit = commit
                    return True
                except AttributeError:
                    # Git returned empty output, file is not tracked
                    self.git_tracked = False
                    self._git_compared_commit = commit
                    return False
                except OSError as error:
                    print('GitGutter failed to create git cache: %s' % error)
                    return False

            # Read file from git incase the compare target has changed
            if self._git_compared_commit == commit:
                return Promise.resolve(False)
            return self.git_read_file(commit).then(write_file)
예제 #7
0
        def check_commit(commit):
            """Check if compare target changed and update git file then.

            If the commit has didn't change since the last run, the temporary
            file is still up to date and git 'show' can be skipped and the
            promise is resolved with False.

            This method uses `git archive` to read the file content from git
            repository to enable support of smudge filters (fixes Issue #74).
            Git applies those smudge filters to some commands like `archive`,
            `diff` and `checkout` only, but not to commands like `show`.

            Arguments:
                commit (string): full hash of the commit the view is currently
                                 compared against.
            Returns:
                bool: True if temporary file was updated, False otherwise.
            """
            def write_file(output):
                """Extract output and write it to a temporary file.

                The function resolves the promise with True to indicate the
                updated git file.
                """
                contents = b''
                if output:
                    # Extract file contents from zipped archive.
                    # The `filelist` contains numberous directories finalized
                    # by exactly one file whose content we are interested in.
                    archive = zipfile.ZipFile(BytesIO(output))
                    contents = archive.read(archive.filelist[-1])
                # Write the content to file
                if not self._git_temp_file:
                    self._git_temp_file = self.tmp_file()
                with open(self._git_temp_file, 'wb') as file:
                    file.write(contents)
                # finally update git hash if file was updated
                self._git_compared_commit = commit
                self.git_tracked = bool(contents)
                return True

            # Read file from git incase the compare target has changed
            if self._git_compared_commit == commit:
                return Promise.resolve(False)
            return self.git_read_file(commit).then(write_file)
예제 #8
0
    def run_command(self, args, decode=True):
        """Run a git command asynchronously and return a Promise.

        Arguments:
            args    - a list of arguments used to create the git subprocess.
            decode  - if True the git's output is decoded assuming utf-8
                      which is the default output encoding of git.
        """
        def read_output(resolve):
            """Start git process and forward its output to the Resolver."""
            try:
                if os.name == 'nt':
                    startupinfo = subprocess.STARTUPINFO()
                    startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
                else:
                    startupinfo = None
                proc = subprocess.Popen(args=args,
                                        cwd=self._git_tree,
                                        startupinfo=startupinfo,
                                        stdout=subprocess.PIPE,
                                        stderr=subprocess.PIPE,
                                        stdin=subprocess.PIPE)
                if _HAVE_TIMEOUT:
                    stdout, stderr = proc.communicate(timeout=30)
                else:
                    stdout, stderr = proc.communicate()
            except OSError as error:
                print('GitGutter failed to run git: %s' % error)
                stdout = b''
            except TimeoutExpired:
                proc.kill()
                stdout, stderr = proc.communicate()
            finally:
                if decode:
                    resolve(stdout.decode('utf-8').strip())
                else:
                    resolve(stdout)

        def run_async(resolve):
            set_timeout(lambda: read_output(resolve), 10)

        return Promise(run_async)
예제 #9
0
        def run_diff(updated_git_file):
            # if both temp files were not updated, diff is not necessary.
            # Resolve with None to indicate this special situation.
            updated_view_file = self.update_view_file()
            if not updated_view_file and not updated_git_file:
                return Promise.resolve(None)

            args = [
                settings.git_binary_path,
                'diff',
                '-U0',
                '--no-color',
                '--no-index',
                settings.ignore_whitespace,
                settings.patience_switch,
                self._git_temp_file,
                self._view_temp_file,
            ]
            args = list(filter(None, args))  # Remove empty args
            return self.run_command(args=args, decode=False).then(decode_diff)
예제 #10
0
    def handle_files(self, additional_args):
        """Run git ls-files to check for untracked or ignored file."""
        if self._git_tree:

            def is_nonempty(results):
                """Determine if view's file is in git's index.

                If the view's file is not part of the index
                git returns empty output to stdout.
                """
                return bool(results)

            args = [
                settings.git_binary_path,
                'ls-files',
                '--other',
                '--exclude-standard',
            ] + additional_args + [
                os.path.join(self._git_tree, self._git_path),
            ]
            args = list(filter(None, args))  # Remove empty args
            return self.run_command(args).then(is_nonempty)
        return Promise.resolve(False)
예제 #11
0
 def callback(async_value):
     self.assertEqual(async_value, 999)
     return Promise(worker_async2)
예제 #12
0
 def test_promise_resolve(self):
     promise = Promise.resolve(999)
     self.assertTrue(promise._is_resolved())
     self.assertEqual(promise._get_value(), 999)