Title: [235981] trunk/Tools
Revision
235981
Author
dba...@webkit.org
Date
2018-09-13 11:07:22 -0700 (Thu, 13 Sep 2018)

Log Message

Add Copy WebKit Permalink plugin for Sublime Text
https://bugs.webkit.org/show_bug.cgi?id=189589

Rubber-stamped by Joseph Pecoraro.

Port the Copy WebKit Permalink Automator service to a Sublime Text plugin. Once installed you can
use the plugin to copy to the Clipboard a trac.webkit.org hyperlink to the selected line in the
active document with or without blame annotations.

Once installed, you can Control-click (on Mac) or right-click (on Windows and Linux) on a line and
choose Copy WebKit Permalink or Copy WebKit Permalink to Blame from the context menu to copy to the
Clipboard a permanent hyperlink to the selected line without or with blame annotations, respectively.
On Mac you can also invoke the same functionality using the keyboard shortcuts Command + Shift + Control + C
and Command + Shift + Control + Option + C, respectively.

* CopyPermalink/Sublime Text/CopyWebKitPermalink/Context.sublime-menu: Added.
* CopyPermalink/Sublime Text/CopyWebKitPermalink/CopyWebKitPermalink.py: Added.
* CopyPermalink/Sublime Text/CopyWebKitPermalink/Default (OSX).sublime-keymap: Added.
* CopyPermalink/Sublime Text/INSTALL: Added.
* CopyPermalink/Xcode/Copy WebKit Permalink.workflow/Contents/Info.plist: Renamed from Tools/CopyPermalink/Copy WebKit Permalink.workflow/Contents/Info.plist.
* CopyPermalink/Xcode/Copy WebKit Permalink.workflow/Contents/document.wflow: Renamed from Tools/CopyPermalink/Copy WebKit Permalink.workflow/Contents/document.wflow.
* CopyPermalink/Xcode/INSTALL: Renamed from Tools/CopyPermalink/README.

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/Tools/ChangeLog (235980 => 235981)


--- trunk/Tools/ChangeLog	2018-09-13 18:07:13 UTC (rev 235980)
+++ trunk/Tools/ChangeLog	2018-09-13 18:07:22 UTC (rev 235981)
@@ -1,3 +1,28 @@
+2018-09-13  Daniel Bates  <daba...@apple.com>
+
+        Add Copy WebKit Permalink plugin for Sublime Text
+        https://bugs.webkit.org/show_bug.cgi?id=189589
+
+        Rubber-stamped by Joseph Pecoraro.
+
+        Port the Copy WebKit Permalink Automator service to a Sublime Text plugin. Once installed you can
+        use the plugin to copy to the Clipboard a trac.webkit.org hyperlink to the selected line in the
+        active document with or without blame annotations.
+
+        Once installed, you can Control-click (on Mac) or right-click (on Windows and Linux) on a line and
+        choose Copy WebKit Permalink or Copy WebKit Permalink to Blame from the context menu to copy to the
+        Clipboard a permanent hyperlink to the selected line without or with blame annotations, respectively.
+        On Mac you can also invoke the same functionality using the keyboard shortcuts Command + Shift + Control + C
+        and Command + Shift + Control + Option + C, respectively.
+
+        * CopyPermalink/Sublime Text/CopyWebKitPermalink/Context.sublime-menu: Added.
+        * CopyPermalink/Sublime Text/CopyWebKitPermalink/CopyWebKitPermalink.py: Added.
+        * CopyPermalink/Sublime Text/CopyWebKitPermalink/Default (OSX).sublime-keymap: Added.
+        * CopyPermalink/Sublime Text/INSTALL: Added.
+        * CopyPermalink/Xcode/Copy WebKit Permalink.workflow/Contents/Info.plist: Renamed from Tools/CopyPermalink/Copy WebKit Permalink.workflow/Contents/Info.plist.
+        * CopyPermalink/Xcode/Copy WebKit Permalink.workflow/Contents/document.wflow: Renamed from Tools/CopyPermalink/Copy WebKit Permalink.workflow/Contents/document.wflow.
+        * CopyPermalink/Xcode/INSTALL: Renamed from Tools/CopyPermalink/README.
+
 2018-09-13  Carlos Garcia Campos  <cgar...@igalia.com>
 
         Unreviewed. Fix WebDriver tests after r235225.

Deleted: trunk/Tools/CopyPermalink/README (235980 => 235981)


--- trunk/Tools/CopyPermalink/README	2018-09-13 18:07:13 UTC (rev 235980)
+++ trunk/Tools/CopyPermalink/README	2018-09-13 18:07:22 UTC (rev 235981)
@@ -1,18 +0,0 @@
-Copy WebKit Permalink is an Xcode service that copies to the Clipboard a permanent hyperlink to the currently selected line in the active Xcode document.
-
-To install:
-
-1. Double-click "Copy WebKit Permalink.workflow".
-2. In the dialog that appears, click Install, then click Done.
-3. Choose Apple menu > System Preferences, click Keyboard, then click Shortcuts.
-4. Select Services on the left, select Copy WebKit Permalink, click in the Keyboard Shortcut field, then press the key combination that you want to use as the keyboard shortcut.
-
-For example, press Command, Shift, Control, and C keys at the same time.
-
-5. Enable "Copy WebKit Permalink" using the checkbox.
-
-The Copy WebKit Permalink service will now appear under Xcode menu > Services.
-
-== Permalink to blame history ==
-
-Hold down the Option key when running the Copy WebKit Permalink service to generate a permalink to the selected line in the blame history for the file.

Added: trunk/Tools/CopyPermalink/Sublime Text/CopyWebKitPermalink/Context.sublime-menu (0 => 235981)


--- trunk/Tools/CopyPermalink/Sublime Text/CopyWebKitPermalink/Context.sublime-menu	                        (rev 0)
+++ trunk/Tools/CopyPermalink/Sublime Text/CopyWebKitPermalink/Context.sublime-menu	2018-09-13 18:07:22 UTC (rev 235981)
@@ -0,0 +1,4 @@
+[
+    { "command": "copy_web_kit_permalink" },
+    { "command": "copy_web_kit_permalink", "args": { "annotate_blame": true }, "caption": "Copy WebKit Permalink to Blame" },
+]

Added: trunk/Tools/CopyPermalink/Sublime Text/CopyWebKitPermalink/CopyWebKitPermalink.py (0 => 235981)


--- trunk/Tools/CopyPermalink/Sublime Text/CopyWebKitPermalink/CopyWebKitPermalink.py	                        (rev 0)
+++ trunk/Tools/CopyPermalink/Sublime Text/CopyWebKitPermalink/CopyWebKitPermalink.py	2018-09-13 18:07:22 UTC (rev 235981)
@@ -0,0 +1,178 @@
+# Copyright (C) 2018 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1.  Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+# 2.  Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in the
+#     documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import os
+import re
+import sublime
+import sublime_plugin
+import subprocess
+
+
+class CopyWebKitPermalinkCommand(sublime_plugin.TextCommand):
+    def run(self, edit, annotate_blame=False):
+        if not self.is_enabled():
+            return
+
+        document_path = self.view.file_name()
+        self._last_svn_info = None
+        self._directory_in_checkout = document_path if os.path.isdir(document_path) else os.path.dirname(document_path)
+        self.determine_vcs_from_path(document_path)
+
+        if not self.path_is_in_webkit_checkout(document_path):
+            return
+
+        line_number, _ = self.view.rowcol(self.view.sel()[0].begin())  # Zero-based
+        line_number = line_number + 1
+
+        path = self.path_relative_to_repository_root_for_path(document_path)
+        revision_info = self.revision_info_for_path(document_path)
+        sublime.set_clipboard(self.permalink_for_path(path, line_number, revision_info, annotate_blame))
+
+    def is_enabled(self):
+        return len(self.view.sel()) > 0 and bool(self.view.file_name())
+
+    def is_visible(self):
+        return self.is_enabled()
+
+    def description(self):
+        return 'Copy WebKit Permalink'
+
+    def determine_vcs_from_path(self, path):
+        if not os.path.isdir(path):
+            path = os.path.dirname(path)
+        self._is_svn = False
+        self._is_git = False
+        self._is_git_svn = False
+        if self.is_svn_directory(path):
+            self._is_svn = True
+            return
+        if self.is_git_svn_directory(path):
+            self._is_git = True
+            self._is_git_svn = True
+            return
+        if self.is_git_directory(path):
+            self._is_git = True
+            return
+
+    def path_is_in_webkit_checkout(self, path):
+        repository_url = self.revision_info_for_path(path).get('repository_url', '')
+        return bool(re.match(r'\w+:\/\/\w+\.webkit.org', repository_url))
+
+    def git_path_relative_to_repository_root_for_path(self, path):
+        return subprocess.check_output(['git', 'ls-tree', '--full-name', '--name-only', 'HEAD', path], cwd=self._directory_in_checkout).decode('utf-8').rstrip()
+
+    def svn_path_relative_to_repository_root_for_path(self, path):
+        return self.svn_info_for_path(path)['path']
+
+    def path_relative_to_repository_root_for_path(self, path):
+        if self._is_svn:
+            return self.svn_path_relative_to_repository_root_for_path(path)
+        if self._is_git:
+            return self.git_path_relative_to_repository_root_for_path(path)
+        return ''
+
+    def revision_info_for_path(self, path):
+        if self._is_svn or self._is_git_svn:
+            return self.svn_revision_info_for_path(path)
+        if self._is_git:
+            return self.git_revision_info_for_path(path)
+        return {}
+
+    def svn_revision_info_for_path(self, path):
+        svn_info = self.svn_info_for_path(path)
+        return {'branch': svn_info['branch'], 'revision': svn_info['revision'], 'repository_url': svn_info['repositoryRoot']}
+
+    def git_revision_info_for_path(self, path):
+        repository_url = subprocess.check_output(['git', 'remote', 'get-url', 'origin'], cwd=self._directory_in_checkout).decode('utf-8').rstrip()
+        revision = subprocess.check_output(['git', 'log', '-1', '--format', '%H', path], cwd=self._directory_in_checkout).decode('utf-8').rstrip()
+        branch = subprocess.check_output(['git', 'symbolic-ref', '-q', 'HEAD'], cwd=self._directory_in_checkout).decode('utf-8').rstrip()
+        branch = re.sub(r'^refs\/heads\/', '', branch) or 'master'
+        return {branch, revision, repository_url}
+
+    def svn_info_for_path(self, path):
+        if self._last_svn_info and self._last_svn_info['path'] == path:
+            # FIXME: We should also ensure that the checkout directory for the cached SVN info is
+            # the same as the specified checkout directory.
+            return self._last_svn_info
+
+        svn_info_command = ['svn', 'info']
+        if self._is_git_svn:
+            svn_info_command = ['git'] + svn_info_command
+        output = subprocess.check_output(svn_info_command + [path], cwd=self._directory_in_checkout).decode('utf-8').rstrip()
+        if not output:
+            return {}
+
+        temp = {}
+        lines = output.splitlines()
+        for line in lines:
+            key, value = line.split(': ', 1)
+            if key and value:
+                temp[key] = value
+
+        svn_info = {
+            'pathAsURL': temp['URL'],
+            'repositoryRoot': temp['Repository Root'],
+            'revision': temp['Revision'],
+        }
+        branch = svn_info['pathAsURL'].replace(svn_info['repositoryRoot'] + '/', '')
+        branch = branch[0:branch.find('/')]
+        svn_info['branch'] = branch
+
+        # Although tempting to use temp['Path'] we cannot because it is relative to self._directory_in_checkout.
+        # And self._directory_in_checkout may not be the top-level checkout directory. We need to compute the
+        # relative path with respect to the top-level checkout directory.
+        svn_info['path'] = svn_info['pathAsURL'].replace('{}/{}/'.format(svn_info['repositoryRoot'], branch), '')
+
+        self._last_svn_info = svn_info
+
+        return svn_info
+
+    @staticmethod
+    def permalink_for_path(path, line_number, revision_info, annotate_blame):
+        revision = '?rev=' + str(revision_info['revision']) if revision_info['revision'] else ''
+        line_number = '#L' + str(line_number) if line_number else ''
+        branch = revision_info['branch'] or 'trunk'
+        annotate_blame = '&annotate=blame' if annotate_blame else ''
+        return 'https://trac.webkit.org/browser/{}/{}{}{}{}'.format(branch, path, revision, annotate_blame, line_number)
+
+    @staticmethod
+    def is_svn_directory(directory):
+        try:
+            subprocess.check_call(['svn', 'info'], cwd=directory)
+        except:
+            return False
+        return True
+
+    @staticmethod
+    def is_git_directory(directory):
+        try:
+            subprocess.check_call(['git', 'rev-parse'], cwd=directory)
+        except:
+            return False
+        return True
+
+    @staticmethod
+    def is_git_svn_directory(directory):
+        try:
+            return bool(subprocess.check_output(['git', 'config', '--get', 'svn-remote.svn.fetch'], cwd=directory, stderr=subprocess.STDOUT).decode('utf-8').rstrip())
+        except:
+            return False

Added: trunk/Tools/CopyPermalink/Sublime Text/CopyWebKitPermalink/Default (OSX).sublime-keymap (0 => 235981)


--- trunk/Tools/CopyPermalink/Sublime Text/CopyWebKitPermalink/Default (OSX).sublime-keymap	                        (rev 0)
+++ trunk/Tools/CopyPermalink/Sublime Text/CopyWebKitPermalink/Default (OSX).sublime-keymap	2018-09-13 18:07:22 UTC (rev 235981)
@@ -0,0 +1,4 @@
+[
+	{ "keys": ["super+ctrl+shift+c"], "command": "copy_web_kit_permalink" },
+    { "keys": ["super+ctrl+option+shift+c"], "command": "copy_web_kit_permalink", "args": { "annotate_blame": true } }
+]

Added: trunk/Tools/CopyPermalink/Sublime Text/INSTALL (0 => 235981)


--- trunk/Tools/CopyPermalink/Sublime Text/INSTALL	                        (rev 0)
+++ trunk/Tools/CopyPermalink/Sublime Text/INSTALL	2018-09-13 18:07:22 UTC (rev 235981)
@@ -0,0 +1,14 @@
+Copy WebKit Permalink is a Sublime Text plugin that copies to the Clipboard a permanent hyperlink to the currently selected line in the active document.
+
+== How to install ==
+
+Copy the directory CopyWebKitPermalink (located in the same directory as this file) to your Packages directory. On Mac, you can open your Packages directory by launching Sublime Text and choosing Sublime Text > Preferences > Browse Packages from the menu bar.
+
+== How to use ==
+
+Control-click (on Mac) or right-click (on Linux and Windows) on a line and select Copy WebKit Permalink or Copy WebKit Permalink to Blame from the context menu to copy to the Clipboard a permanent hyperlink to the selected line without or with blame annotations, respectively.
+
+== Key bindings for Mac ==
+
+Without blame annotations: Command + Shift + Control + C
+With blame annotations: Command + Shift + Control + Option + C

Copied: trunk/Tools/CopyPermalink/Xcode/Copy WebKit Permalink.workflow/Contents/Info.plist (from rev 235979, trunk/Tools/CopyPermalink/Copy WebKit Permalink.workflow/Contents/Info.plist) (0 => 235981)


--- trunk/Tools/CopyPermalink/Xcode/Copy WebKit Permalink.workflow/Contents/Info.plist	                        (rev 0)
+++ trunk/Tools/CopyPermalink/Xcode/Copy WebKit Permalink.workflow/Contents/Info.plist	2018-09-13 18:07:22 UTC (rev 235981)
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>NSServices</key>
+	<array>
+		<dict>
+			<key>NSMenuItem</key>
+			<dict>
+				<key>default</key>
+				<string>Copy WebKit Permalink</string>
+			</dict>
+			<key>NSMessage</key>
+			<string>runWorkflowAsService</string>
+			<key>NSRequiredContext</key>
+			<dict>
+				<key>NSApplicationIdentifier</key>
+				<string>com.apple.dt.Xcode</string>
+			</dict>
+		</dict>
+	</array>
+</dict>
+</plist>

Copied: trunk/Tools/CopyPermalink/Xcode/Copy WebKit Permalink.workflow/Contents/document.wflow (from rev 235979, trunk/Tools/CopyPermalink/Copy WebKit Permalink.workflow/Contents/document.wflow) (0 => 235981)


--- trunk/Tools/CopyPermalink/Xcode/Copy WebKit Permalink.workflow/Contents/document.wflow	                        (rev 0)
+++ trunk/Tools/CopyPermalink/Xcode/Copy WebKit Permalink.workflow/Contents/document.wflow	2018-09-13 18:07:22 UTC (rev 235981)
@@ -0,0 +1,412 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>AMApplicationBuild</key>
+	<string>428</string>
+	<key>AMApplicationVersion</key>
+	<string>2.7</string>
+	<key>AMDocumentVersion</key>
+	<string>2</string>
+	<key>actions</key>
+	<array>
+		<dict>
+			<key>action</key>
+			<dict>
+				<key>AMAccepts</key>
+				<dict>
+					<key>Container</key>
+					<string>List</string>
+					<key>Optional</key>
+					<true/>
+					<key>Types</key>
+					<array>
+						<string>com.apple.applescript.object</string>
+					</array>
+				</dict>
+				<key>AMActionVersion</key>
+				<string>1.0</string>
+				<key>AMApplication</key>
+				<array>
+					<string>Automator</string>
+				</array>
+				<key>AMParameterProperties</key>
+				<dict>
+					<key>source</key>
+					<dict/>
+				</dict>
+				<key>AMProvides</key>
+				<dict>
+					<key>Container</key>
+					<string>List</string>
+					<key>Types</key>
+					<array>
+						<string>com.apple.applescript.object</string>
+					</array>
+				</dict>
+				<key>ActionBundlePath</key>
+				<string>/System/Library/Automator/Run _javascript_.action</string>
+				<key>ActionName</key>
+				<string>Run _javascript_</string>
+				<key>ActionParameters</key>
+				<dict>
+					<key>source</key>
+					<string>/*
+ *  Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ *  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ *  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ *  THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+ObjC.import("Cocoa");
+
+var g_isSVN;
+var g_isGit;
+var g_isGitSVN;
+var g_lastSVNInfo;
+
+var App = Application.currentApplication();
+App.includeStandardAdditions = true;
+
+function run(input, parameters) {
+    var xcodeDocument = xcodeActiveDocument();
+    if (!xcodeDocument)
+        return;
+
+    var xcodeDocumentPath = xcodeDocument.path();
+    determineVCSFromPath(xcodeDocumentPath);
+
+    if (!pathIsInWebKitCheckout(xcodeDocumentPath))
+        return;
+
+    var lineNumber = xcodeSelectedLineInDocument(xcodeDocument);
+    var path = pathRelativeToRepositoryRootForPath(xcodeDocumentPath);
+    var revisionInfo = revisionInfoForPath(xcodeDocumentPath);
+    var annotateBlame = $.NSEvent.modifierFlags &amp; $.NSAlternateKeyMask;
+
+    App.setTheClipboardTo(permalinkForPath(path, lineNumber, revisionInfo, annotateBlame));
+}
+
+function pathIsInWebKitCheckout(path)
+{
+    var repositoryURL = revisionInfoForPath(path).repositoryURL;
+    return !!repositoryURL.match(/^\w+:\/\/\w+\.webkit.org/);
+}
+
+function permalinkForPath(path, lineNumber, revisionInfo, annotateBlame)
+{
+    var revision = revisionInfo.revision ? "?rev=" + revisionInfo.revision : "";
+    var lineNumber = lineNumber ? "#L" + lineNumber : "";
+    var branch = revisionInfo.branch || "trunk";
+    var withBlame = annotateBlame ? "&amp;annotate=blame" : "";
+    return `https://trac.webkit.org/browser/${branch}/${path}${revision}${withBlame}${lineNumber}`;
+}
+
+// MARK: Xcode
+
+function xcodeActiveDocument()
+{
+    var xcode = Application("Xcode");
+    var windows = xcode.windows();
+    var numberOfWindows = windows.length;
+    if (!numberOfWindows)
+        return null;
+
+    // The title of an Xcode Workspace window is the title of the document in the editor pane.
+    // Ignore windows without a name (e.g. "Edit all occurrences of a symbol" pop-up menu).
+    var documentName;
+    for (var i = 0; !documentName &amp;&amp; i &lt; numberOfWindows; ++i)
+        documentName = windows[i].name();
+    if (!documentName)
+        return null;
+
+    // The title of a modified document that has not been saved will have a suffix. Remove
+    // the suffix.
+    const editedSuffix = " — Edited";
+    if (documentName.endsWith(editedSuffix))
+        documentName = documentName.substr(0, documentName.lastIndexOf(editedSuffix));
+    return xcode.documents.byName(documentName);
+}
+
+function xcodeSelectedLineInDocument(xcodeDocument)
+{
+    if (!xcodeDocument)
+        return -1;
+    var range = xcodeDocument.selectedCharacterRange();
+    if (!range)
+        return -1;
+    var beginPosition = range[0] - 1;
+    if (!beginPosition)
+        return 0;
+    // FIXME: It would be more efficient to count the CRLF, CR, or LF characters
+    // in the substring from [0, beginPosition].
+    var lines = xcodeDocument.text().split(/\r?\n|\r/);
+    var numberOfLines = lines.length;
+    var characterCount = 0;
+    var i = 0;
+    do {
+        characterCount += lines[i].length + 1;
+        if (characterCount &gt; beginPosition)
+            break;
+    } while (++i &lt; numberOfLines);
+    return i + 1;
+}
+
+// MARK: VCS utilities
+
+function determineVCSFromPath(path)
+{
+    if (!isDirectory(path))
+        path = dirname(path);
+
+    g_isSVN = false;
+    g_isGit = false;
+    g_isGitSVN = false;
+
+    if (isSVNDirectory(path)) {
+        g_isSVN = true;
+        return;
+    }
+
+    if (isGitSVNDirectory(path)) {
+        g_isGit = true;
+        g_isGitSVN = true;
+        return;
+    }
+
+    if (isGitDirectory(path)) {
+        g_isGit = true;
+        return;
+    }
+}
+
+function pathRelativeToRepositoryRootForPath(path)
+{
+    var directoryInCheckout = isDirectory(path) ? path : dirname(path);
+    if (g_isSVN)
+        return svnPathRelativeToRepositoryRootForPath(path, directoryInCheckout);
+    if (g_isGit)
+        return gitPathRelativeToRepositoryRootForPath(path, directoryInCheckout);
+    return "";
+}
+
+function gitPathRelativeToRepositoryRootForPath(path, directoryInCheckout)
+{
+    return App.doShellScript(`git -C '${directoryInCheckout}' ls-tree --full-name --name-only HEAD '${path}'`);
+}
+
+function svnPathRelativeToRepositoryRootForPath(path, directoryInCheckout)
+{
+    return svnInfoForPath(path, directoryInCheckout).path;
+}
+
+function revisionInfoForPath(path)
+{
+    var directoryInCheckout = isDirectory(path) ? path : dirname(path);
+    if (g_isSVN || g_isGitSVN)
+        return svnRevisionInfoForPath(path, directoryInCheckout);
+    if (g_isGit)
+        return gitRevisionInfoForPath(path, directoryInCheckout);
+    return "";
+}
+
+function svnRevisionInfoForPath(path, directoryInCheckout)
+{
+    var svnInfo = svnInfoForPath(path, directoryInCheckout);
+    return { "branch": svnInfo.branch, "revision": svnInfo.revision, "repositoryURL": svnInfo.repositoryRoot };
+}
+
+function gitRevisionInfoForPath(path, directoryInCheckout)
+{
+    var repositoryURL = App.doShellScript(`git -C '${directoryInCheckout}' remote get-url origin`);
+    var revision = App.doShellScript(`git -C '${directoryInCheckout}' log -1 --format='%H' '${path}'`);
+    var branch = App.doShellScript(`git -C '${directoryInCheckout}' symbolic-ref -q HEAD`);
+    branch = branch.replace(/^refs\/heads\//, "") || "master";
+    return { branch, revision, repositoryURL };
+}
+
+function svnInfoForPath(path, directoryInCheckout)
+{
+    if (g_lastSVNInfo &amp;&amp; g_lastSVNInfo.path === path) {
+        // FIXME: We should also ensure that the checkout directory for the cached SVN info is
+        // the same as the specified checkout directory.
+        return g_lastSVNInfo;
+    }
+
+    var svnInfoCommand = "svn info";
+    if (g_isGitSVN)
+        svnInfoCommand = "git " + svnInfoCommand;
+    var output = App.doShellScript(`cd '${directoryInCheckout}' &amp;&amp; ${svnInfoCommand} '${path}'`, {"alteringLineEndings": false});
+    if (!output)
+        return { };
+
+    var temp = { };
+    var lines = output.split("\n");
+    for (var line of lines) {
+        var [key, value] = line.split(": ", 2);
+        if (key &amp;&amp; value)
+            temp[key] = value;
+    }
+    var svnInfo = {
+        "pathAsURL": temp["URL"],
+        "repositoryRoot": temp["Repository Root"],
+        "revision": temp["Revision"],
+    };
+    var branch = svnInfo.pathAsURL.replace(svnInfo.repositoryRoot + "/", "");
+    branch = branch.substr(0, branch.indexOf("/"));
+    svnInfo.branch = branch;
+
+    // Although tempting to use temp["Path"] we cannot because it is relative to directoryInCheckout.
+    // And directoryInCheckout may not be the top-level checkout directory. We need to compute the
+    // relative path with respect to the top-level checkout directory.
+    svnInfo.path = svnInfo.pathAsURL.replace(`${svnInfo.repositoryRoot}/${branch}/`, "");
+
+    g_lastSVNInfo = svnInfo;
+
+    return svnInfo;
+}
+
+function isSVNDirectory(directory)
+{
+    try {
+        App.doShellScript(`cd '${directory}' &amp;&amp; svn info &gt; /dev/null 2&gt;&amp;1`);
+        return true;
+    } catch (e) {
+        return false;
+    }
+}
+
+function isGitDirectory(directory)
+{
+    try {
+        App.doShellScript(`git -C '${directory}' rev-parse &gt; /dev/null 2&gt;&amp;1`);
+        return true;
+    } catch (e) {
+        return false;
+    }
+}
+
+function isGitSVNDirectory(directory)
+{
+    var output = "";
+    try {
+        output = App.doShellScript(`git -C '${directory}' config --get svn-remote.svn.fetch 2&gt;&amp;1`);
+    } catch (e) { }
+    return output !== "";
+}
+
+// MARK: Utilities
+
+function isDirectory(path)
+{
+    try {
+        return App.infoFor(path).folder;
+    } catch (e) {
+        return false;
+    }
+}
+
+function dirname(path)
+{
+    return path.substr(0, path.lastIndexOf("/"));
+}
+</string>
+				</dict>
+				<key>BundleIdentifier</key>
+				<string>com.apple.Automator.RunJavaScript</string>
+				<key>CFBundleVersion</key>
+				<string>1.0</string>
+				<key>CanShowSelectedItemsWhenRun</key>
+				<false/>
+				<key>CanShowWhenRun</key>
+				<true/>
+				<key>Category</key>
+				<array>
+					<string>AMCategoryUtilities</string>
+				</array>
+				<key>Class Name</key>
+				<string>RunJavaScriptAction</string>
+				<key>InputUUID</key>
+				<string>0C0655EF-7893-4A61-ADD0-BA803AF3C2CD</string>
+				<key>Keywords</key>
+				<array>
+					<string>Run</string>
+					<string>_javascript_</string>
+				</array>
+				<key>OutputUUID</key>
+				<string>5BAD8148-07E0-4FA2-AAA1-990A7BE926FC</string>
+				<key>UUID</key>
+				<string>24BFD6CC-7A96-42C2-8469-5D83FA921DB2</string>
+				<key>UnlocalizedApplications</key>
+				<array>
+					<string>Automator</string>
+				</array>
+				<key>arguments</key>
+				<dict>
+					<key>0</key>
+					<dict>
+						<key>default value</key>
+						<string>function run(input, parameters) {
+	
+	// Your script goes here
+
+	return input;
+}</string>
+						<key>name</key>
+						<string>source</string>
+						<key>required</key>
+						<string>0</string>
+						<key>type</key>
+						<string>0</string>
+						<key>uuid</key>
+						<string>0</string>
+					</dict>
+				</dict>
+				<key>isViewVisible</key>
+				<true/>
+				<key>location</key>
+				<string>480.500000:316.000000</string>
+				<key>nibPath</key>
+				<string>/System/Library/Automator/Run _javascript_.action/Contents/Resources/Base.lproj/main.nib</string>
+			</dict>
+			<key>isViewVisible</key>
+			<true/>
+		</dict>
+	</array>
+	<key>connectors</key>
+	<dict/>
+	<key>workflowMetaData</key>
+	<dict>
+		<key>serviceApplicationBundleID</key>
+		<string>com.apple.dt.Xcode</string>
+		<key>serviceApplicationPath</key>
+		<string>/Applications/Xcode.app</string>
+		<key>serviceInputTypeIdentifier</key>
+		<string>com.apple.Automator.nothing</string>
+		<key>serviceOutputTypeIdentifier</key>
+		<string>com.apple.Automator.nothing</string>
+		<key>serviceProcessesInput</key>
+		<integer>0</integer>
+		<key>workflowTypeIdentifier</key>
+		<string>com.apple.Automator.servicesMenu</string>
+	</dict>
+</dict>
+</plist>

Copied: trunk/Tools/CopyPermalink/Xcode/INSTALL (from rev 235979, trunk/Tools/CopyPermalink/README) (0 => 235981)


--- trunk/Tools/CopyPermalink/Xcode/INSTALL	                        (rev 0)
+++ trunk/Tools/CopyPermalink/Xcode/INSTALL	2018-09-13 18:07:22 UTC (rev 235981)
@@ -0,0 +1,18 @@
+Copy WebKit Permalink is an Xcode service that copies to the Clipboard a permanent hyperlink to the currently selected line in the active Xcode document.
+
+== How to install and use ==
+
+1. Double-click "Copy WebKit Permalink.workflow".
+2. In the dialog that appears, click Install, then click Done.
+3. Choose Apple menu > System Preferences, click Keyboard, then click Shortcuts.
+4. Select Services on the left, select Copy WebKit Permalink, click in the Keyboard Shortcut field, then press the key combination that you want to use as the keyboard shortcut.
+
+For example, press Command, Shift, Control, and C keys at the same time.
+
+5. Enable "Copy WebKit Permalink" using the checkbox.
+
+The Copy WebKit Permalink service will now appear under Xcode menu > Services.
+
+== How to use ==
+
+In Xcode, use the key binding you setup above or choose Xcode > Services > Copy WebKit Permalink to copy to the Clipboard a permanent hyperlink to the selected line. Hold down the Option key when running the service to copy to the Clipboard a permanent hyperlink to the selected line with blame annotations.
\ No newline at end of file
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to