| 300 | } |
| 301 | |
| 302 | func parseFile(opts BrowseOptions, f string) (p string, start int, end int, err error) { |
| 303 | if f == "" { |
| 304 | return |
| 305 | } |
| 306 | |
| 307 | parts := strings.SplitN(f, ":", 3) |
| 308 | if len(parts) > 2 { |
| 309 | err = fmt.Errorf("invalid file argument: %q", f) |
| 310 | return |
| 311 | } |
| 312 | |
| 313 | p = filepath.ToSlash(parts[0]) |
| 314 | if !path.IsAbs(p) && !opts.HasRepoOverride { |
| 315 | p = path.Join(opts.PathFromRepoRoot(), p) |
| 316 | if p == "." || strings.HasPrefix(p, "..") { |
| 317 | p = "" |
| 318 | } |
| 319 | } |
| 320 | if len(parts) < 2 { |
| 321 | return |
| 322 | } |
| 323 | |
| 324 | if idx := strings.IndexRune(parts[1], '-'); idx >= 0 { |
| 325 | start, err = strconv.Atoi(parts[1][:idx]) |
| 326 | if err != nil { |
| 327 | err = fmt.Errorf("invalid file argument: %q", f) |
| 328 | return |
| 329 | } |
| 330 | end, err = strconv.Atoi(parts[1][idx+1:]) |
| 331 | if err != nil { |
| 332 | err = fmt.Errorf("invalid file argument: %q", f) |
| 333 | } |
| 334 | return |
| 335 | } |
| 336 | |
| 337 | start, err = strconv.Atoi(parts[1]) |
| 338 | if err != nil { |
| 339 | err = fmt.Errorf("invalid file argument: %q", f) |
| 340 | } |
| 341 | end = start |
| 342 | return |
| 343 | } |
| 344 | |
| 345 | func isNumber(arg string) bool { |
| 346 | _, err := strconv.Atoi(strings.TrimPrefix(arg, "#")) |