Tuesday, 24 May 2016

ag và tìm hoài không thấy

Nếu bạn chưa biết ag là gì thì hãy đọc ngay tại đâyag có một sức mạnh kinh hoàng mà chỉ cần một lần thử, bạn sẽ tin.

ag giúp tìm kiếm từ khoá nhanh hơn grep nhiều lần, câu lệnh ngắn hơn vài lần, và đôi khi nó còn tỏ ra thông minh một cách đáng sợ nữa.
Ví dụ dưới đây trình bày một trường hợp nếu ag trong thư mục con ``cmd`` thì tìm thấy kết quả còn nếu ag từ thư mục parent thì lại không thấy gì:
src/github.com/syncthing/syncthing/cmd $ ag cert.pem
syncthing/locations.go
47:     locCertFile:      "${config}/cert.pem",
49:     locHTTPSCertFile: "${config}/https-cert.pem",

syncthing/main.go
376:    certFile, keyFile := filepath.Join(dir, "cert.pem"), filepath.Join(dir, "key.pem")
Thấy kết quả trong file syncthing/main.go
Giờ chuyển đến thư mục parent:

src/github.com/syncthing/syncthing/cmd $ cd ..
src/github.com/syncthing/syncthing $ ag cert.pem
lib/discover/global_test.go
118:    cert, err := tlsutil.NewCertificate(dir+"/cert.pem", dir+"/key.pem", "syncthing", 1024)
190:    cert, err := tlsutil.NewCertificate(dir+"/cert.pem", dir+"/key.pem", "syncthing", 1024)

man/syncthing-config.5
60:.B \fBcert.pem\fP, \fBkey.pem\fP
64:.B \fBhttps\-cert.pem\fP, \fBhttps\-key.pem\fP

man/syncthing-device-ids.7
45:private key (\fBkey.pem\fP) and a self signed certificate (\fBcert.pem\fP). The self
99:An advanced user could replace the \fBkey.pem\fP and \fBcert.pem\fP files with a

test/cli_test.go
78:     for _, f := range []string{"home.out/config.xml", "home.out/cert.pem", "home.out/key.pem"} {
121:                            for _, f := range []string{"home.out/config.xml", "home.out/cert.pem", "home.out/key.pem", "home.out/https-cert.pem", "home.out/https-key.pem"} {

Không thấy kết quả nào trong cmd cả. Điều này đã làm mất điểm của tác giả trong một cuộc đua tìm bug :'(

Lý do? hãy cùng đi tìm!
ag có option -D để in ra output để debug.
-D --debug              Ridiculous debugging (probably not useful)
chạy từ thư mục parent:
$ ag cert.pem  -D
DEBUG: Loading ignore file ./.gitignore.
...
DEBUG: path_start ./cmd filename syncthing
DEBUG: pattern !syncthing doesn't match file syncthing
DEBUG: pattern !syncthing doesn't match file syncthing/
DEBUG: file syncthing ignored because name matches static pattern syncthing
...

Như vậy đã rõ, ag "thông minh" đọc các file .gitignore và loại bỏ chúng khỏi kết quả tìm kiếm.
Trong thư mục parent có "syncthing" trong file .gitignore, vì vậy nó bị loại khỏi kết quả tìm kiếm.

Giải pháp
khi tiếp cận repo lạ, hãy bảo syncthing không loại bỏ các kết quả nếu nó match path với các path trong .gitignore.
$ ag -a cert.pem | ag main
cmd/syncthing/main.go:376:    certFile, keyFile := filepath.Join(dir, "cert.pem"), filepath.Join(dir, "key.pem")
Giờ thì đã thấy file main.go dưới thư mục syncthing trong kết quả.
 -a --all-types          Search all files (doesn't include hidden files
                          or patterns from ignore files)
Liên quan
https://git-scm.com/docs/gitignore

Kết luận
khi dùng ag chơi ở ruộng lạ, nhớ dùng "trừ a" (-a).
Hết.
hvn at FAMILUG.org