Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
itchyny committed Nov 8, 2015
0 parents commit ef3adf7
Show file tree
Hide file tree
Showing 69 changed files with 693 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mkr
build
snapshot
34 changes: 34 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
sudo: false
language: go
go:
- 1.4
env: PATH=/home/travis/gopath/bin:$PATH
install:
- go get github.com/laher/goxc
- go get github.com/aryann/difflib
script:
- goxc -t
- make test
- make cross
deploy:
provider: releases
api_key:
secure: kBfgx18Or35j1LeFbJ5DvY7vwx2zfJ1L4A8p1mF/uGKecsVBwvAxB4LijdM8ZEDW3fUbK+3DX/GLS8rZrX96FkRTxXyMjrQZ7pKzqg6iE9JsDCflvQQJfmu4DnmqFAx9pU6MjD8lBuEX/xRQ9TCjR+O5CMwRPbocsTbJdfEC++8YYzq9/woO0ZrsOItthioucdtScvmbMc7VtvssNfc2lczGKHzcT7NpLC6/TvwIbvWO10Ntbwp0/1xC3wxYxTUd/Aiz0xSbGQw/1aIgid3w0pJuwtytbv/HafNggrehHxa87d/cAf1mY7HDw04A2ECSD7DAhHn4fKLUTO8CPVh+ria7JhlJ5AnRZazrQqBqxWWK7DILGnN2j4uX8c2b19cID68V3V7KzPE1xwmBb5c1YNIyNzA5gHKhIw40FG9U9hGlhs4E4238D36CcSa+JjVpvnRzJXeiO6kR1ja9D4XnR7cn+ARGuF33z5e+/CozoMJgVHWjxnws8NIEqaejBjet1AqQqBzntyi2A/eF9T1CS2Igv9fJytMI2xf80DIMcBM4hvXCL1JwBerT5rZnYwJydxHmXsf4pEPVE5V6GyN3X0Xj+Zh9mZ+NGXjyziFHy2L/OBVkK4W+MTg0ioAPGfzlacNYnIKEmTMujAjmOjMmU5EVE76ijgUdAYLVM88aYJc=
file:
- snapshot/rexdep_darwin_386.zip
- snapshot/rexdep_darwin_amd64.zip
- snapshot/rexdep_freebsd_386.zip
- snapshot/rexdep_freebsd_amd64.zip
- snapshot/rexdep_freebsd_arm.zip
- snapshot/rexdep_linux_386.tar.gz
- snapshot/rexdep_linux_amd64.tar.gz
- snapshot/rexdep_linux_arm.tar.gz
- snapshot/rexdep_snapshot_amd64.deb
- snapshot/rexdep_snapshot_armhf.deb
- snapshot/rexdep_snapshot_i386.deb
- snapshot/rexdep_windows_386.zip
- snapshot/rexdep_windows_amd64.zip
on:
repo: itchyny/rexdep
tags: true
all_branches: false
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2015 itchyny

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
39 changes: 39 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
BIN = rexdep
VERSION = v0.0.0
DESCRIPTION = Roughly extract dependency from source code
AUTHOR = itchyny

BUILD_FLAGS = "\
-X main.Author \"$(AUTHOR)\" \
-X main.Description \"$(DESCRIPTION)\" \
-X main.Name \"$(BIN)\" \
-X main.Version \"$(VERSION)\" \
"

all: clean test build

test: build
go test -v ./...

build: deps
go build -ldflags=$(BUILD_FLAGS) -o build/$(BIN) .

install: deps
go install -ldflags=$(BUILD_FLAGS)

cross: deps
goxc -build-ldflags=$(BUILD_FLAGS) \
-os="linux darwin freebsd windows" -arch="386 amd64 arm" -d . \
-resources-include='README*' -n $(BIN)

deps:
go get -d -v .

testdeps:
go get -d -v -t .

clean:
rm -rf build snapshot debian
go clean

.PHONY: test build cross deps testdeps clean
93 changes: 93 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# rexdep
[![Travis Build Status](https://travis-ci.org/itchyny/rexdep.svg?branch=master)](https://travis-ci.org/itchyny/rexdep)
[![Latest Version](https://img.shields.io/github/release/itchyny/rexdep.svg)](https://github.com/itchyny/rexdep/releases)

### Roughly extract dependency from source code
The rexdep command is a tool for extracting dependency relation from a set of source codes.
The idea of rexdep is very simple.
For example, consider a situation that `test1.c` includes `test2.c` and `test3.c`.
```c
#include "test2.c"
#include "test3.c"

int main...
```
The file `test1.c` depends on `test2.c` and `test3.c`.
This relation can be easily extracted by matching a simple regular expression.
```
$ grep '^#include ".*"' test1.c | sed 's/^#include *"\(.*\)"/\1/'
test2.c
test3.c
```
This simple way can be used for many languages.
For example, `import` keyword is used in Python and Haskell, `require` is used in Ruby.

The rexdep command enables to specify the `pattern` to extract the module dependency.
For the above example, you can also use rexdep to extract the dependency.
```
$ rexdep --pattern '^\s*#include\s*"(\S+)"' test1.c
"test1.c" -> "test2.c";
"test1.c" -> "test3.c";
```
You can of course specify multiple files, and you can even specify directories and rexdep recursively investigate the source files under the subdirectories.
You may use `^\s*#include\s*[<"](\S+)[>"]` for C language or `^\s*import +(?:qualified +)?(\S+)` for Haskell language.
Allowing the user to specify by regular expression, it can be used for various languages.

There are some tools targeting on specific languages.
They investigate the source code at the level of abstract syntax tree and therefore are much powerful.
The rexdep command, on the other hand, simply checks the source code by a regular expression given by the user.
It may not as powerful as AST-level tools, but the idea of rexdep is very simple and can be used for many languages.

## Examples
### [Git](https://github.com/git/git)
```sh
$ git clone --depth 1 https://github.com/git/git
$ rexdep --pattern '^\s*#include\s*[<"](\S+)[>"]' --digraph git ./git/*.h | dot -Tpng -o git.png
```
[![git](https://raw.githubusercontent.com/wiki/itchyny/rexdep/image/git-1.png)](https://raw.githubusercontent.com/wiki/itchyny/rexdep/image/git.png)
The source code of Git is large and the above example checks only header files.

### [Vim](https://github.com/vim/vim)
```sh
$ git clone --depth 1 https://github.com/vim/vim
$ rexdep --pattern '^\s*#include\s*[<"](\S+)[>"]' --digraph vim ./vim/src/*.{c,h} | dot -Tpng -o vim.png
```
[![vim](https://raw.githubusercontent.com/wiki/itchyny/rexdep/image/vim-1.png)](https://raw.githubusercontent.com/wiki/itchyny/rexdep/image/vim.png)
The above image is a part of the output. We notice that the structure is very flat and may files include `vim.h`.

### [consul](https://github.com/hashicorp/consul)
```sh
$ git clone --depth 1 https://github.com/hashicorp/consul
$ rexdep --pattern '\s*"(?:\S+/)+(\S+)"' --start '^import \($' --end '^\)$' --digraph go --trimext $(find ./consul/ -name '*.go' | grep -v '_test') | dot -Tpng -o consul.png
```
[![consul](https://raw.githubusercontent.com/wiki/itchyny/rexdep/image/consul-1.png)](https://raw.githubusercontent.com/wiki/itchyny/rexdep/image/consul.png)

### [pandoc](https://github.com/jgm/pandoc)
```sh
$ git clone --depth 1 https://github.com/jgm/pandoc
$ rexdep --pattern '^\s*import +(?:qualified +)?(\S+(?:Pandoc)\S+)' --module '^module +(\S+(?:Pandoc)\S+)' --digraph pandoc --recursive ./pandoc/src/ | dot -Tpng -o pandoc.png
```
[![pandoc](https://raw.githubusercontent.com/wiki/itchyny/rexdep/image/pandoc-1.png)](https://raw.githubusercontent.com/wiki/itchyny/rexdep/image/pandoc.png)

## Installation
### Download binary from GitHub Releases
[Releases ・ itchyny/rexdep - GitHub](https://github.com/itchyny/rexdep/releases)

### Build from source
```bash
$ go get github.com/itchyny/rexdep
$ go install github.com/itchyny/rexdep
```

## Usage
To be documented.

```sh
$ rexdep --pattern 'import (\S+)' FILES
```

## Author
itchyny (https://github.com/itchyny)

## License
This software is released under the MIT License, see LICENSE.
49 changes: 49 additions & 0 deletions action.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package main

import (
"fmt"

"github.com/codegangsta/cli"
)

func action(ctx *cli.Context) {
config, errors := makeConfig(ctx)
if errors != nil {
for _, err := range errors {
fmt.Fprintf(ctx.App.Writer, err.Error())
}
cli.ShowAppHelp(ctx)
} else {
dependencies, errors := gatherDependency(config)
for _, err := range errors {
fmt.Fprintf(ctx.App.Writer, "# "+err.Error()+"\n")
}
indent := ""
if config.Digraph != "" {
fmt.Fprintf(ctx.App.Writer, "digraph \"%s\" {\n", config.Digraph)
indent = " "
}
for _, dependency := range dependencies {
for _, to := range dependency.To {
fmt.Fprintf(ctx.App.Writer, "%s\"%s\" -> \"%s\";\n", indent, dependency.From, to)
}
}
if config.Digraph != "" {
fmt.Fprintf(ctx.App.Writer, "}\n")
}
}
}

func gatherDependency(config *Config) ([]*Dependency, []error) {
var errors []error
var dependencies []*Dependency
for _, path := range config.Paths {
deps, err := extract(path, config)
if err != nil {
errors = append(errors, err...)
} else {
dependencies = append(dependencies, deps...)
}
}
return dependencies, errors
}
85 changes: 85 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package main

import (
"errors"
"regexp"

"github.com/codegangsta/cli"
)

type Config struct {
Pattern *regexp.Regexp
Module *regexp.Regexp
Start *regexp.Regexp
End *regexp.Regexp
Digraph string
Paths []string
Recursive bool
Trimext bool
}

func makeConfig(ctx *cli.Context) (*Config, []error) {
var errs []error

if ctx.GlobalBool("help") {
errs = append(errs, errors.New(""))
return nil, errs
}

if ctx.GlobalString("pattern") == "" {
errs = append(errs, errors.New("Specify --pattern (-p) to extract imports.\n\n"))
}

pattern, err := regexp.Compile(ctx.GlobalString("pattern"))
if err != nil {
errs = append(errs, errors.New(regexErrorMessage("--pattern (-p)")+err.Error()+"\n\n"))
}

module, err := regexp.Compile(ctx.GlobalString("module"))
if err != nil {
errs = append(errs, errors.New(regexErrorMessage("--module (-m)")+err.Error()+"\n\n"))
}
if ctx.GlobalString("module") == "" {
module = nil
}

start, err := regexp.Compile(ctx.GlobalString("start"))
if err != nil {
errs = append(errs, errors.New(regexErrorMessage("--start (-s)")+err.Error()+"\n\n"))
}
if ctx.GlobalString("start") == "" {
start = nil
}

end, err := regexp.Compile(ctx.GlobalString("end"))
if err != nil {
errs = append(errs, errors.New(regexErrorMessage("--end (-e)")+err.Error()+"\n\n"))
}
if ctx.GlobalString("end") == "" {
end = nil
}

paths := ctx.Args()
if len(paths) == 0 {
errs = append(errs, errors.New("Specify source codes.\n\n"))
}

if len(errs) > 0 {
return nil, errs
}

return &Config{
Pattern: pattern,
Module: module,
Start: start,
End: end,
Digraph: ctx.GlobalString("digraph"),
Paths: paths,
Recursive: ctx.GlobalBool("recursive"),
Trimext: ctx.GlobalBool("trimext"),
}, nil
}

func regexErrorMessage(flag string) string {
return "The argument of " + flag + " is invalid. Specify a valid regular expression.\n"
}
6 changes: 6 additions & 0 deletions dependency.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package main

type Dependency struct {
From string
To []string
}
Loading

0 comments on commit ef3adf7

Please sign in to comment.