summaryrefslogtreecommitdiffstats
path: root/tools/emacs/trybot.el
blob: 784241d2241a8f4a4751d92f6ac8c409f9df355b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
; To use this,
; 1) Add to init.el:
;    (setq-default chrome-root "/path/to/chrome/src/")
;    (add-to-list 'load-path (concat chrome-root "tools/emacs"))
;    (require 'trybot)
; 2) Run on trybot output:
;    M-x trybot
;
; To hack on this,
; M-x eval-buffer
; M-x trybot-test-win  or  M-x trybot-test-mac

(defvar chrome-root nil
  "Path to the src/ directory of your Chrome checkout.")

(defun get-chrome-root ()
  (or chrome-root default-directory))

; Hunt down from the top, case correcting each path component as needed.
; Currently does not keep a cache.  Returns nil if no matching file can be
; figured out.
(defun case-corrected-filename (filename)
  (save-match-data
    (let ((path-components (split-string filename "/"))
          (corrected-path (file-name-as-directory (get-chrome-root))))
      (mapc
       (function
        (lambda (elt)
          (if corrected-path
              (let ((next-component
                     (car (member-ignore-case
                           elt (directory-files corrected-path)))))
                (setq corrected-path
                      (and next-component
                           (file-name-as-directory
                            (concat corrected-path next-component))))))))
       path-components)
      (if corrected-path
          (file-relative-name (directory-file-name corrected-path)
                              (get-chrome-root))
        nil))))

(defun trybot-fixup-win ()
  "Fix up Windows-specific output."

  ; Fix Windows paths ("d:\...\src\").
  (save-excursion
    (while (re-search-forward "\\(^.:\\\\.*\\\\src\\\\\\)\\(.*?\\)[(:]" nil t)
      (replace-match "" nil t nil 1)
      ; Line now looks like:
      ;  foo\bar\baz.cc error message here
      ; We want to fixup backslashes in path into forward slashes,
      ; without modifying the error message - by matching up to the
      ; first colon above (which will be just beyond the end of the
      ; filename) we can use the end of the match as a limit.
      (subst-char-in-region (point) (match-end 0) ?\\ ?/)
      ; See if we can correct the file name casing.
      (let ((filename (buffer-substring (match-beginning 2) (match-end 2))))
        (if (and (not (file-exists-p filename))
                 (setq filename (case-corrected-filename filename)))
            (replace-match filename t t nil 2))))))

(defun trybot-fixup-maclin ()
  "Fix up Mac/Linux output."
  (save-excursion
    (while (re-search-forward "^/b/build/[^ ]*/src/" nil t)
      (replace-match ""))))

(defun trybot-fixup (type-hint)
  "Parse and fixup the contents of the current buffer as trybot output."

  ; XXX is there something I should so so this stuff doesn't end up on the
  ; undo stack?

  ;; Fixup paths.
  (cd (get-chrome-root))

  (goto-char (point-min))

  ;; Fix up path references.
  (cond ((eq type-hint 'win) (trybot-fixup-win))
        ((eq type-hint 'mac) (trybot-fixup-maclin))
        ((eq type-hint 'linux) (trybot-fixup-maclin))
        (t (trybot-fixup-win) (trybot-fixup-maclin)))

  (compilation-mode))

(defun trybot-test (type-hint filename)
  "Load the given test data filename and do the trybot parse on it."

  (switch-to-buffer (get-buffer-create "*trybot-test*"))
  (let ((inhibit-read-only t)
        (coding-system-for-read 'utf-8-dos))
    (erase-buffer)
    (insert-file-contents
       (concat (get-chrome-root) "tools/emacs/" filename))

    (trybot-fixup type-hint)))

(defun trybot-test-win ()
  "Load the Windows test data and do the trybot parse on it."
  (interactive)
  (trybot-test 'win "trybot-windows.txt"))
(defun trybot-test-mac ()
  "Load the Mac test data and do the trybot parse on it."
  (interactive)
  (trybot-test 'mac "trybot-mac.txt"))
(defun trybot-test-linux ()
  "Load the Linux test data and do the trybot parse on it."
  (interactive)
  (trybot-test 'linux "trybot-linux.txt"))

(defun trybot (url)
  "Fetch a trybot URL and fix up the output into a compilation-mode buffer."
  (interactive "sURL to trybot stdout (leave empty to use clipboard): ")

  ;; Yank URL from clipboard if necessary.
  (when (= (length url) 0)
    (with-temp-buffer
      (clipboard-yank)
      (setq url (buffer-string))))

  ;; TODO: fixup URL to append /text if necessary.

  ;; Extract the body out of the URL.
  ; TODO: delete HTTP headers somehow.
  (let ((inhibit-read-only t)
        (coding-system-for-read 'utf-8-dos)
        (type-hint (cond ((string-match "/win/" url) 'win)
                         ((string-match "/mac/" url) 'mac)
                         ; Match /linux, /linux_view, etc.
                         ((string-match "/linux" url) 'linux)
                         (t 'unknown))))
    (switch-to-buffer (get-buffer-create "*trybot*"))
    (buffer-swap-text (url-retrieve-synchronously url))

    (trybot-fixup type-hint)))

(provide 'trybot)