summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.config.sample12
-rw-r--r--.gitignore4
-rw-r--r--Makefile48
-rw-r--r--README.md50
l---------ject1
-rwxr-xr-xscripts/base.py108
-rwxr-xr-xscripts/find.py148
-rwxr-xr-xscripts/html.py649
-rwxr-xr-xscripts/ject.py16
-rwxr-xr-xscripts/view.py195
10 files changed, 1231 insertions, 0 deletions
diff --git a/.config.sample b/.config.sample
new file mode 100644
index 0000000..1d8d61a
--- /dev/null
+++ b/.config.sample
@@ -0,0 +1,12 @@
+viewer:less -RXE
+
+git-linux:/home/morimoto/WORK/linux
+html-default-cols:200
+html-default-rows:300
+
+# color = escape sequence
+key:33
+status:01;46
+team:32
+tag:01;47
+error:01;41
diff --git a/.gitignore b/.gitignore
index 1f89d9f..61f189e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,5 @@
.config
+scripts/__pycache__/
+index.html
+html
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..165d3c9
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,48 @@
+HTML = ./scripts/html.py
+FIND = ./scripts/find.py
+ALLYAML = $(shell ${FIND} -all)
+FOLDERS = $(subst ./,,$(shell cd ./projects; find -type d))
+TEAM = Core IO MM
+MEMBER = BSP Geert Jacopo Kaneko Kieran Laurent Magnus Marek Morimoto Niklas Shimoda Simon Ulrich Wolfram NoAssignee
+STATUS = New Active Blocked Paused Done Abandoned
+NOPARAM = menu subindex body index
+
+all:
+ @make -s LISTS="${FOLDERS}" TARGET=summary loop
+ @make -s LISTS="${NOPARAM}" TARGET=noparam loop
+ @make -s LISTS="${ALLYAML}" TARGET=file loop
+ @make -s LISTS="${MEMBER}" TARGET=finds EXP1=member EXP2=-a loop
+ @make -s LISTS="${STATUS}" TARGET=finds EXP1=status EXP2=-s loop
+ @make -s LISTS="${TEAM}" TARGET=finds EXP1=team EXP2=-t loop
+ @make -s bsp
+ @make -s index.html
+
+index.html:
+ @ln html/index.html .
+
+$(dir ${FILE}):
+ @mkdir -p $@
+
+${FILE}: ${HTML_OPTION2} $(dir ${FILE}) ${HTML}
+ echo $@
+ ${HTML} ${HTML_OPTION1} ${HTML_OPTION2} > $@
+loop:
+ for list in ${LISTS}; do\
+ make PARAM=$${list} EXP1=${EXP1} EXP2=${EXP2} ${TARGET};\
+ done;
+
+basic:
+ make HTML_OPTION1="${HTML_OPTION1}" HTML_OPTION2="${HTML_OPTION2}" FILE=${FILE} ${FILE}
+summary:
+ make HTML_OPTION1=summary HTML_OPTION2=projects/${PARAM} FILE=html/${PARAM}/summary.html basic
+file:
+ make HTML_OPTION1=task HTML_OPTION2=${PARAM} FILE=$(subst yaml,html,$(subst projects,html,${PARAM})) basic
+noparam:
+ make HTML_OPTION1=${PARAM} FILE=html/${PARAM}.html basic
+bsp:
+ make HTML_OPTION1=bsp HTML_OPTION2="${ALLYAML}" FILE=html/bsp.html basic
+finds:
+ make HTML_OPTION1="${EXP1} ${PARAM}" HTML_OPTION2="$(shell ${FIND} ${EXP2} ${PARAM})" FILE=html/${PARAM}.html basic
+clean:
+ @rm -fr html
+ @rm -fr *.html
diff --git a/README.md b/README.md
index 46e2483..e3dd89a 100644
--- a/README.md
+++ b/README.md
@@ -15,3 +15,53 @@ developed to aid the creation and manipulation of the data sources.
use cases in the future. See:
- https://pykwalify.readthedocs.io/en/unstable/extensions.html#how-custom-validation-works
+
+# ject
+
+## How to use ?
+You can check project via ject command.
+You need to install python-yaml package. If you are using ubuntu, it will be
+
+ > sudo apt install python3-pip
+ > sudo pip3 install --upgrade pip
+ > sudo pip3 install pyyaml
+
+You need to have **.config** file. You can copy sample .config, and edit it
+
+`cp .config.sample .config`
+
+## options
+
+ * key : show matched key task
+ - ject 7ddd3743-fa13-4966-bcf0-10609b873ab5
+ - ject 7ddd3743-fa13-4966-bcf0-10609b873ab5 e704e989-ccaa-48a5-8f58-28c5b93467ff
+ * -s : show matched status task
+ * -ns : show unmatched status task
+ - ject -s Active ... # single match
+ - ject -s Active,New ... # multi match
+ - ject -ns Done # not match
+ * -a : show matched assignee task
+ * -as : show unmatched assignee task
+ - ject -a Wolfram ...
+ - ject -na Morimoto,Shimoda ...
+ * -t : show matched team task
+ * -at : show unmatched team task
+ - ject -t IO,MM ...
+ - ject -nt Core ...
+ * -f : show with file name
+ * -r : show with relationships
+ * --oneline : show one line
+ * --all : show all tasks
+
+# HTML
+
+## How to create HTML ?
+It is easy ! just "make"
+You can find index.html on top of periject folder
+But, You need to have **.config** file. You can copy sample .config, and edit it
+
+Your .config need to have "git-linux" and it need to have bsp repository
+You can add it by
+
+ > git remote add bsp git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas-bsp.git
+
diff --git a/ject b/ject
new file mode 120000
index 0000000..54e059e
--- /dev/null
+++ b/ject
@@ -0,0 +1 @@
+scripts/ject.py \ No newline at end of file
diff --git a/scripts/base.py b/scripts/base.py
new file mode 100755
index 0000000..1a6396e
--- /dev/null
+++ b/scripts/base.py
@@ -0,0 +1,108 @@
+#! /usr/bin/env python3
+#===============================
+#
+# base
+#
+# 2019/02/07 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+#===============================
+import os
+import re
+import subprocess
+
+#====================================
+#
+# base
+#
+# it supports do/run/run1 for using external command
+#
+#====================================
+class base:
+ __top = os.path.abspath(__file__ + "/../../");
+ __key = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
+
+ #--------------------
+ # chomp
+ #--------------------
+ def chomp(self, text):
+ return re.sub(r"\n$", r"", text);
+
+ #--------------------
+ # top()
+ #--------------------
+ def top(self):
+ return base.__top;
+
+ #--------------------
+ # is_key()
+ #--------------------
+ def is_key(self, key):
+ return re.match(base.__key, key);
+
+ #--------------------
+ # color
+ #--------------------
+ def color(self, color, text):
+ return "\033[{}m{}\033[0m".format(self.config(color), text)
+
+ #--------------------
+ # do()
+ #
+ # do command
+ #--------------------
+ def do(self, command):
+ return subprocess.run(command, shell=True).returncode;
+
+ #--------------------
+ # tolist()
+ #--------------------
+ def tolist(self, string):
+ if (len(string) > 0):
+ return string.split('\n');
+
+ return [];
+
+ #--------------------
+ # run()
+ #
+ # run command and get result as plane text
+ #--------------------
+ def run(self, command):
+
+ # Ughhhh
+ # I don't like python external command !!
+ # (ノ `Д´)ノ go away !!
+ return self.chomp(subprocess.Popen(command, shell=True, stdout=subprocess.PIPE).\
+ communicate()[0].decode("utf-8"));
+
+ #--------------------
+ # run1()
+ #
+ # run command and get result as list
+ #--------------------
+ def runl(self, command):
+
+ # call run() and exchange result as array
+ #
+ # "xxxxxxx
+ # yyyyyyy
+ # zzzzzzz"
+ # ->
+ # ["xxxxxxx",
+ # "yyyyyyy",
+ # "zzzzzzz"]
+ return self.tolist(self.run(command));
+
+ #--------------------
+ # config()
+ #
+ # read settings from config
+ #--------------------
+ def config(self, item):
+ if (not os.path.exists("{}/.config".format(self.top()))):
+ print("\nplease copy .config.sample to .config\n" +
+ "and edit it for your environment\n");
+ exit();
+
+ config = self.run("grep {} {}/.config | cut -d : -f2".\
+ format(item, self.top()));
+ return self.chomp(config);
diff --git a/scripts/find.py b/scripts/find.py
new file mode 100755
index 0000000..e1e86ae
--- /dev/null
+++ b/scripts/find.py
@@ -0,0 +1,148 @@
+#! /usr/bin/env python3
+#===============================
+#
+# find
+#
+# 2019/02/07 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+#===============================
+import sys
+import os
+import re
+
+import base
+
+#====================================
+#
+# find
+#
+#====================================
+class find(base.base):
+
+ #--------------------
+ # default_arg
+ #--------------------
+ def default_arg(self, arg):
+ # return [] for -all
+ #
+ # replace -a NoAssignee to -na ""
+ #
+ # add "-ns Done" automatically
+ # if user doesn't specify "-s" or "-ns"
+ match = 0
+ for i in range(len(arg)):
+ if (arg[i] == "-all"):
+ return []
+ if ((arg[i] == "-a") and
+ (arg[i+1] == "NoAssignee")):
+ arg[i] = "-na"
+ arg[i+1] = ""
+ if ((arg[i] == "-s") or (arg[i] == "-ns")):
+ match = 1
+
+ if (not match):
+ arg += ["-ns", "Done"]
+
+ return arg
+
+ #--------------------
+ # parse_option
+ #--------------------
+ def parse_option(self, arg, option, char, hit):
+
+ op = "-l" # hit
+ if (not hit):
+ op = "-L" # not hit
+
+ match = 0
+ for cmd in arg:
+ if (cmd == option):
+ match = 1
+ elif (match):
+ # Wolfram,Shimoda
+ # ->
+ # (Wolfram|Shimoda)
+ tgt = "({})".format(cmd.replace(",", "|"))
+
+ self.files = self.run("echo \"{}\" | xargs egrep {} \"{}:\s+{}\"".\
+ format(self.files, op, char, tgt))
+ return
+
+ #--------------------
+ # parse_files
+ #--------------------
+ def parse_files(self, arg):
+
+ # find specified key files if exist
+ for key in arg:
+ if (not self.is_key(key)):
+ continue
+
+ if (len(self.files) > 0):
+ self.files += "\n"
+
+ self.files += self.run("egrep -l \"key:\s+{}\" -r {}/projects".\
+ format(key, self.top()))
+
+ # find specified folder files if exist
+ if (len(self.files) == 0):
+ did = 0
+ for folder in arg:
+ if (os.path.isdir(folder)):
+ did = 1
+ self.files += self.run("find {} -mindepth 1 -maxdepth 1 -name \"*.yaml\" | grep -v schema".\
+ format(folder))
+ if (did):
+ return
+
+ # all project files if no files
+ if (len(self.files) == 0):
+ self.files = self.run("find {}/projects -name \"*.yaml\" | grep -v schema".\
+ format(self.top()))
+
+ #--------------------
+ # __init__
+ #--------------------
+ def __init__(self, arg):
+ super().__init__()
+
+ self.files = ""
+
+ self.parse_files(arg)
+
+ arg = self.default_arg(arg)
+
+ # -all: all
+ # -s : matched status
+ # -ns : not matched status
+ # -a : matched assignee
+ # -na : not matched assignee
+ # -t : matched team
+ # -nt : not matched team
+ if (self.files):
+ self.parse_option(arg, "-s", "status", 1)
+ self.parse_option(arg, "-ns", "status", 0)
+ self.parse_option(arg, "-a", "assignee", 1)
+ self.parse_option(arg, "-na", "assignee", 0)
+ self.parse_option(arg, "-t", "team", 1)
+ self.parse_option(arg, "-nt", "team", 0)
+
+ #--------------------
+ # get
+ #--------------------
+ def get(self):
+ return self.tolist(self.files)
+
+ #--------------------
+ # show
+ #--------------------
+ def show(self):
+ if (self.files):
+ print(self.files)
+
+#====================================
+#
+# As command
+#
+#====================================
+if __name__=='__main__':
+ find(sys.argv).show()
diff --git a/scripts/html.py b/scripts/html.py
new file mode 100755
index 0000000..537ee52
--- /dev/null
+++ b/scripts/html.py
@@ -0,0 +1,649 @@
+#! /usr/bin/env python3
+#===============================
+#
+# html
+#
+# 2019/02/18 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+#===============================
+import sys
+import os
+import re
+
+import base
+import find
+import view
+
+#====================================
+#
+# html
+#
+#====================================
+class html(base.base):
+
+ __head = 0
+ __noclose = ["input",
+ "frame",
+ "link",
+ "br",
+ ]
+
+ #--------------------
+ # option
+ #--------------------
+ def option(self, dic):
+ if (dic):
+ self.dic.update(dic)
+
+ #--------------------
+ # __init__
+ #--------------------
+ def __init__(self, mark, dic = None):
+ super().__init__()
+
+ self.dic = {}
+ self.mark = mark
+ self.option(dic)
+ self.txt = ""
+
+ #--------------------
+ # open
+ #--------------------
+ def open(self, ret = 0):
+
+ self.txt = ""
+
+ if (ret):
+ for i in range(html.__head):
+ self.txt += "\t"
+
+ self.txt += "<{}".format(self.mark)
+ for d in self.dic:
+ self.txt += " {}=\"{}\"".format(d, self.dic[d])
+ self.txt += ">"
+ html.__head += 1
+
+ #--------------------
+ # close
+ #--------------------
+ def close(self, ret = 0):
+ html.__head -= 1
+ # no end-mark
+ if (self.mark in html.__noclose):
+ return
+
+ if (ret):
+ for i in range(html.__head):
+ self.txt += "\t"
+ self.txt += "</{}>".format(self.mark)
+
+ #--------------------
+ # text
+ #--------------------
+ def text(self, txt = ""):
+ self.open()
+ self.txt += txt
+ self.close()
+ return self.txt
+
+ #--------------------
+ # print
+ #--------------------
+ def print(self, txt = ""):
+
+ self.open(1)
+ self.txt += txt
+ self.close(0)
+ print(self.txt)
+
+ #--------------------
+ # for with
+ #--------------------
+ def __enter__(self):
+ self.open(1)
+ print(self.txt)
+ self.txt = ""
+ return self
+ def __exit__(self, exception_type, exception_value, traceback):
+ self.close(1)
+ print(self.txt)
+ self.txt = ""
+
+#====================================
+#
+# periject_html
+#
+#====================================
+class periject_html(base.base):
+
+ def __init__(self):
+ super().__init__()
+ self.git = self.config("git-linux")
+
+ def relpath(self, path, frm):
+ return os.path.relpath("{}/{}".format(self.top(), path), frm)
+
+ def relpath_y2h(self, file, frm):
+ return os.path.relpath(file.replace("yaml", "html").replace("projects", "html"), frm)
+
+ def git_title(self, id):
+ return self.run("git -C {} log -1 {} --format=%s".format(self.git, id))
+
+ def bsp_url(self, id):
+ return "https://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas-bsp.git/commit/?id={}".format(id)
+
+ def upstream_url(self, id):
+ return "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id={}".format(id)
+
+ #--------------------
+ # index
+ #--------------------
+ def index(self):
+ # | | |
+ # |menu|body|
+ # | | |
+ with html("frameset", {"cols":"{},*".format(self.config("html-default-cols"))}):
+ html("frame", {"src":"./html/menu.html", "name":"menu"}).print()
+ html("frame", {"src":"./html/subindex.html", "name":"body"}).print()
+
+ #--------------------
+ # summary
+ #--------------------
+ def subindex(self):
+ # -------
+ # summary
+ # -------
+ # body
+ # -------
+ with html("frameset", {"rows":"{},*".format(self.config("html-default-rows"))}):
+ html("frame", {"src":"./summary.html", "name":"summary"}).print()
+ html("frame", {"src":"./body.html", "name":"subbody"}).print()
+
+ #--------------------
+ # summary
+ #--------------------
+ def ___summary(self, status, dir, files):
+
+ if (not len(files)):
+ return
+
+ html("h3").print(html("a", {"target":"summary",
+ "href":self.relpath("html/{}.html".format(status), dir)}).text(status))
+
+ with html("table", {"border":"1"}):
+ with html("tr"):
+ html("th").print("file")
+ html("th").print("team")
+ html("th").print("assignee")
+ html("th").print("title")
+ for file in files:
+ v = view.viewer([file])
+ v.set_data(file)
+
+ subbody = html("a", {"target":"subbody"})
+ summary = html("a", {"target":"summary"})
+ with html("tr"):
+ subbody.option({"href":self.relpath_y2h(file, dir)})
+ html("td").print(subbody.text(os.path.basename(file).replace(".yaml", "")))
+
+ team = v.get_data("team")
+ summary.option({"href":self.relpath("html/{}.html".format(team), dir)})
+ html("td").print(summary.text(team))
+
+ assignee = v.get_data("assignee")
+ if (not len(assignee)):
+ assignee = "NoAssignee"
+ summary.option({"href":self.relpath("html/{}.html".format(assignee), dir)})
+ html("td").print(summary.text(assignee))
+
+ html("td").print(v.get_data("title"))
+
+ #--------------------
+ # summary
+ #--------------------
+ def __summary(self, title, dir, files):
+ # -------
+ # summary
+ # -------
+ #
+ # -------
+ if (title):
+ html("h2").print(title)
+
+ new = []
+ active = []
+ blocked = []
+ paused = []
+ done = []
+ abandoned = []
+
+ for file in files:
+ v = view.viewer([file])
+ v.set_data(file)
+
+ status = v.get_data("status")
+ if (status == "New"):
+ new.append(file)
+ elif (status == "Active"):
+ active.append(file)
+ elif (status == "Blocked"):
+ blocked.append(file)
+ elif (status == "Paused"):
+ paused.append(file)
+ elif (status == "Done"):
+ done.append(file)
+ else:
+ abandoned.append(file)
+
+ self.___summary("New", dir, new)
+ self.___summary("Active", dir, active)
+ self.___summary("Blocked", dir, blocked)
+ self.___summary("Paused", dir, paused)
+ self.___summary("Done", dir, done)
+ self.___summary("Abandoned", dir, abandoned)
+
+ #--------------------
+ # summary
+ #--------------------
+ def summary(self, argv):
+
+ dir = os.path.normpath(argv[0])
+
+ # -------
+ # summary
+ # -------
+ #
+ # -------
+ self.__summary(dir, self.top() + "/" + dir, find.find([dir]).get())
+
+ #--------------------
+ # menu_folder
+ #--------------------
+ def menu_folder(self, current):
+ folders = self.runl("cd {}; ls -F | grep /".format(current))
+ path = current.replace("./projects", ".")
+ link = html("a", {"target":"summary",
+ "href":"{}/summary.html".format(path)})
+
+ html("li").print(link.text(os.path.basename(current)))
+
+ if (not folders):
+ return
+
+ with html("ul"):
+ for folder in folders:
+ dir = os.path.basename(folder)
+ self.menu_folder("{}/{}".format(current, folder[:-1]))
+
+ #--------------------
+ # menu_assignee
+ #--------------------
+ def menu_assignee(self):
+ # from project.schema.yaml
+ with html("ul"):
+ for assignee in ['BSP', 'Geert', 'Jacopo', 'Kaneko', 'Kieran', 'Laurent', 'Magnus', 'Marek',
+ 'Morimoto', 'Niklas', 'Shimoda', 'Simon', 'Ulrich', 'Wolfram', "NoAssignee"]:
+ html("li").print(html("a", {"target":"summary",
+ "href":"./{}.html".format(assignee)}).text(assignee))
+
+ #--------------------
+ # menu_status
+ #--------------------
+ def menu_status(self):
+ # from project.schema.yaml
+ with html("ul"):
+ for status in ['New', 'Active', 'Blocked', 'Paused', 'Done', 'Abandoned']:
+ html("li").print(html("a", {"target":"summary",
+ "href":"./{}.html".format(status)}).text(status))
+
+ #--------------------
+ # menu_team
+ #--------------------
+ def menu_team(self):
+ # from project.schema.yaml
+ with html("ul"):
+ for status in ['Core', 'IO', 'MM']:
+ html("li").print(html("a", {"target":"summary",
+ "href":"./{}.html".format(status)}).text(status))
+
+ #--------------------
+ # menu_bsp
+ #--------------------
+ def menu_bsp(self):
+ html("a", {"target":"summary",
+ "href":"./bsp.html"}).print("BSP patch list")
+
+ #--------------------
+ # menu
+ #--------------------
+ def menu(self):
+
+ with html("body"):
+ html("h1").print("Folder")
+ with html("ul"):
+ self.menu_folder("./projects")
+
+ html("h1").print("Assignee")
+ self.menu_assignee()
+
+ html("h1").print("Status")
+ self.menu_status()
+
+ html("h1").print("Team")
+ self.menu_team()
+
+ html("h1").print("BSP")
+ self.menu_bsp()
+
+ #--------------------
+ # body
+ #--------------------
+ def body(self):
+ with html("body"):
+ html("div").print("select tasks from menu")
+
+ #--------------------
+ # task_status
+ #--------------------
+ def task_status(self, v):
+ dir = os.path.dirname(v.file)
+ assignee = v.get_data("assignee")
+ status = v.get_data("status")
+ team = v.get_data("team")
+
+ if (not len(assignee)):
+ assignee = "NoAssignee"
+
+ with html("table", {"border":"1"}):
+ with html("tr"):
+ html("th").print("file")
+ html("th").print("status")
+ html("th").print("team")
+ html("th").print("assignee")
+ html("th").print("key")
+
+ with html("tr"):
+ html("td").print(os.path.relpath(v.file, self.top()))
+ html("td").print(html("a", {"target":"summary",
+ "href":self.relpath("html/{}.html".format(status), dir)}).text(status))
+ html("td").print(html("a", {"target":"summary",
+ "href":self.relpath("html/{}.html".format(team), dir)}).text(team))
+ html("td").print(html("a", {"target":"summary",
+ "href":self.relpath("html/{}.html".format(assignee), dir)}).text(assignee))
+ html("td").print(v.get_data("key"))
+
+ #--------------------
+ # _task_relation
+ #--------------------
+ def _task_relation(self, relationship, v, item):
+
+ current_dir = os.path.dirname(v.file)
+ related_file = v.get_related_file(relationship[item])
+
+ if (not os.path.exists(related_file)):
+ with html("tr"):
+ html("td").print(item)
+ html("td").print("Unknown({})".format(related_file))
+ return
+
+ rv = view.viewer([related_file])
+ rv.set_data(related_file)
+ with html("tr"):
+ html("td").print(item)
+ html("td").print(html("a", {"href":
+ self.relpath_y2h(related_file, current_dir)}).text(rv.get_data("title")))
+
+ #--------------------
+ # task_relation
+ #--------------------
+ def task_relation(self, v):
+
+ relationships = v.get_data("relationships")
+ if (not relationships):
+ return
+
+ current_dir = os.path.dirname(v.file)
+
+ with html("table", {"border":"1"}):
+ for relationship in relationships:
+ if ("parent" in relationship):
+ self._task_relation(relationship, v, "parent")
+ if ("depends" in relationship):
+ self._task_relation(relationship, v, "depends")
+ if ("blocks" in relationship):
+ self._task_relation(relationship, v, "blocks")
+
+ #--------------------
+ # task_head
+ #--------------------
+ def task_head(self, v):
+
+ with html("table"):
+ with html("tr"):
+ with html("td"):
+ self.task_status(v)
+ with html("td"):
+ self.task_relation(v)
+
+ #--------------------
+ # task_commit_bsp
+ #--------------------
+ def task_commit_bsp(self, bsp_list):
+
+ cnt = 0
+
+ with html("ul"):
+ for bsp in bsp_list:
+ cnt += 1
+ html("li").print(html("a", {"href":self.bsp_url(bsp),
+ "target":"subbody"}).text(self.git_title(bsp)))
+
+ return cnt
+
+ #--------------------
+ # __task_commit_upstream
+ #--------------------
+ def __task_commit_upstream(self, v, upstream, item):
+ if (not item in upstream):
+ return 0
+
+ commit = upstream[item]
+
+ with html("tr"):
+ html("td").print(item)
+ html("td").print(html("a", {"href":self.upstream_url(commit),
+ "target":"subbody"}).text(self.git_title(commit)))
+
+ return 1
+
+ #--------------------
+ # task_commit_upstream
+ #--------------------
+ def task_commit_upstream(self, v):
+ upstream = v.get_data("upstream")
+ if (not len(upstream)):
+ return 0
+
+ cnt = 0
+ with html("table"):
+ for up in upstream:
+ cnt += self.__task_commit_upstream(v, up, "torvalds")
+ for up in upstream:
+ cnt += self.__task_commit_upstream(v, up, "next")
+
+ return cnt
+
+ #--------------------
+ # task_commit
+ #--------------------
+ def task_commit(self, v):
+
+ bsp = v.get_data("bsp-commits")
+ if (not bsp):
+ return
+
+ with html("table", {"border":"1"}):
+ with html("tr"):
+ html("th").print("BSP")
+ html("th").print("upstream")
+ with html("tr"):
+ with html("td"):
+ self.task_commit_bsp(bsp)
+ with html("td"):
+ self.task_commit_upstream(v)
+
+ #--------------------
+ # task_comment
+ #--------------------
+ def task_comment(self, v):
+ comments = v.get_data("comments")
+ if (not comments):
+ return
+
+ with html("ul"):
+ for comment in comments:
+ str = re.search(r'(https?://[\w/:%#\$&\?\(\)~\.=\+\-]+)', comment)
+ if (str):
+ a = html("a", {"href":str.group(),
+ "target":"_blank"})
+ comment = str.string[:str.start()] + a.text(str.group()) + str.string[str.end():]
+
+ html("li").print(comment)
+
+ #--------------------
+ # task
+ #--------------------
+ def task(self, argv):
+ v = view.viewer([argv[0]])
+ v.set_data(argv[0])
+
+ with html("body"):
+ html("h1").print(v.get_data("title"))
+ self.task_head(v)
+ self.task_commit(v)
+ self.task_comment(v)
+
+ #--------------------
+ # member
+ #--------------------
+ def member(self, argv):
+
+ mem = argv.pop(0)
+
+ with html("body"):
+ self.__summary(mem, "{}/html".format(self.top()), argv)
+
+ #--------------------
+ # status
+ #--------------------
+ def status(self, argv):
+
+ argv.pop(0)
+
+ with html("body"):
+ self.__summary(None, "{}/html".format(self.top()), argv)
+
+ #--------------------
+ # team
+ #--------------------
+ def team(self, argv):
+
+ team = argv.pop(0)
+
+ with html("body"):
+ self.__summary(team, "{}/html".format(self.top()), argv)
+
+ #--------------------
+ # bsp
+ #--------------------
+ def bsp(self, argv):
+
+ a = html("a", {"target":"subbody"})
+ cnt_bsp = 0
+ cnt_up = 0
+ cnt_all = 0
+ cnt_done= 0
+ tmp = 0
+ with html("body"):
+ html("h1").print("BSP patch list")
+
+ with html("table", {"border":"1"}):
+ with html("tr"):
+ html("th").print("file")
+ html("th").print("BSP")
+ html("th").print("upstream")
+
+ for file in argv:
+ v = view.viewer([file])
+ v.set_data(file)
+
+ bsp = v.get_data("bsp-commits")
+ if (not len(bsp)):
+ continue
+
+ cnt_all += 1
+ with html("tr"):
+ a.option({"href":
+ os.path.relpath(file.replace("yaml", "html").replace("projects", "html"), "{}/html".format(self.top()))})
+ html("td").print(a.text(os.path.basename(file).replace(".yaml", "")))
+
+ with html("td"):
+ tmp = self.task_commit_bsp(bsp)
+ cnt_bsp += tmp
+
+ with html("td"):
+ up = self.task_commit_upstream(v)
+ if (up):
+ cnt_up += tmp
+ cnt_done += 1
+
+ html("p").print("bsp:{}/upstream:{} = {:.1f}%".format(cnt_bsp, cnt_up, cnt_up * 100 /cnt_bsp))
+ html("p").print("task:{}/done:{} = {:.1f}%".format(cnt_all, cnt_done, cnt_done * 100 /cnt_all))
+
+ #--------------------
+ # print
+ #--------------------
+ def print(self, argv):
+
+ # remove this script
+ argv.pop(0)
+
+ cmd = sys.argv.pop(0)
+ with html("html"):
+ if (cmd == "index"):
+ # html.py index
+ self.index()
+ elif(cmd == "subindex"):
+ # html.py subindex
+ self.subindex()
+ elif (cmd == "body"):
+ # html.py body
+ self.body()
+ elif (cmd == "menu"):
+ # html.py menu
+ self.menu()
+ elif (cmd == "summary"):
+ # html.py summary projects/linux/io
+ self.summary(sys.argv)
+ elif (cmd == "task"):
+ # html.py task projects/linux/io/xxx.yaml
+ self.task(sys.argv)
+ elif (cmd == "member"):
+ # ./script/find.py -a Wolfram | xargs ./script/html.py menber Wolfram
+ self.member(sys.argv)
+ elif (cmd == "status"):
+ # ./script/find.py -s Active | xargs ./script/html.py status Active
+ self.status(sys.argv)
+ elif (cmd == "team"):
+ # ./script/find.py -t Core | xargs ./script/html.py status Core
+ self.team(sys.argv)
+ elif (cmd == "bsp"):
+ # ./script/find.py -a | xargs ./script/html.py bsp
+ self.bsp(sys.argv)
+
+#====================================
+#
+# As command
+#
+#====================================
+if __name__=='__main__':
+ periject_html().print(sys.argv)
diff --git a/scripts/ject.py b/scripts/ject.py
new file mode 100755
index 0000000..b0b469f
--- /dev/null
+++ b/scripts/ject.py
@@ -0,0 +1,16 @@
+#! /usr/bin/env python3
+#===============================
+#
+# ject
+#
+# 2019/02/12 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+#===============================
+import sys
+
+import find
+import view
+
+param = sys.argv
+
+view.viewer(param + find.find(param).get()).show()
+
diff --git a/scripts/view.py b/scripts/view.py
new file mode 100755
index 0000000..48c6f71
--- /dev/null
+++ b/scripts/view.py
@@ -0,0 +1,195 @@
+#! /usr/bin/env python3
+#===============================
+#
+# viewer
+#
+# 2019/02/07 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+#===============================
+import yaml
+import sys
+import os
+import re
+
+import base
+
+#====================================
+#
+# viewer
+#
+#====================================
+class viewer(base.base):
+
+ #--------------------
+ # parse
+ #
+ # -f : with file
+ # -r : with relationships
+ # --oneline: one line
+ #--------------------
+ def parse(self, arg):
+ for arg in arg:
+ if (arg == "-f"):
+ self.with_file = 1
+ elif (arg == "-r"):
+ self.with_rel = 1
+ elif (arg == "--oneline"):
+ self.one_line = 1
+ elif (os.path.exists(arg) and
+ re.match("{}/projects".format(self.top()),
+ os.path.abspath(arg))):
+ self.files += [arg]
+
+ #--------------------
+ # __init__
+ #--------------------
+ def __init__(self, arg):
+
+ self.text = ""
+ self.files = []
+ self.with_file = 0
+ self.with_rel = 0
+ self.one_line = 0
+
+ self.parse(arg)
+ self.data = {}
+ self.file = ""
+
+ #--------------------
+ # get_item
+ #--------------------
+ def get_item(self, data):
+ # Ughhhh
+ # All Yaml data is "dictionary", and not simple to getting data !!
+ # ( `⌒´)d I hate you !!
+ return list(data)[0]
+
+ #--------------------
+ # get_related_file
+ #--------------------
+ def get_related_file(self, data):
+ file = self.run("egrep -l \"key:\s+{}\" -r {}/projects".\
+ format(data, self.top()))
+ if (file):
+ return file
+ else:
+ return data
+
+ #--------------------
+ # set_data
+ # get_data
+ #--------------------
+ def set_data(self, file):
+ F = open(file, "r+")
+ self.data = yaml.load(F)
+ F.close()
+ self.file = file
+
+ def get_data(self, key):
+ if (key in self.data):
+ data = self.data[key]
+ if (data):
+ return data
+ return []
+
+ #--------------------
+ # make_one
+ # for --oneline
+ #--------------------
+ def make_one(self, tag, file):
+
+ if (len(self.text) > 0):
+ self.text += "\n"
+
+ if (tag):
+ self.text += "{:<22}".format(self.color("tag", tag))
+
+ if (not os.path.exists(file)):
+ self.text += self.color("error", "No such task ({})".format(file))
+ return
+
+ self.set_data(file)
+
+ # show "key"
+ self.text += "{}: {}".format(
+ self.color("key", self.get_data("key")),
+ self.get_data("title"))
+
+ # show relationships
+ relationships = self.get_data("relationships")
+ if ((not tag) and self.with_rel and relationships):
+ for d in relationships:
+ self.make_one(self.get_item(d.keys()),
+ self.get_related_file(self.get_item(d.values())))
+
+ #--------------------
+ # make_full
+ # for normal
+ #--------------------
+ def make_full(self, tag, file):
+
+ if (len(self.text) > 0):
+ self.text += "\n"
+
+ if (tag):
+ self.text += "{:<22}".format(self.color("tag", tag))
+
+ if (not os.path.exists(file)):
+ self.text += self.color("error", "No such task ({})".format(file))
+ return
+
+ self.set_data(file)
+
+ # show "key"
+ self.text += "{}, {}, {}\n".format(
+ self.color("key", self.get_data("key")),
+ self.color("status", self.get_data("status")),
+ self.color("team", self.get_data("team")));
+
+ # show title
+ self.text += "Title: {}\n".format(self.get_data("title"))
+
+ # show assignee
+ assignee = self.get_data("assignee")
+ if (len(assignee)):
+ self.text += "Assignee: {}\n".format(assignee)
+
+ if (self.with_file):
+ self.text += "File: {}\n".format(
+ os.path.abspath(file).replace("{}/".format(self.top()), ""))
+
+ # show comments
+ comments = self.get_data("comments")
+ if (comments):
+ for comment in comments:
+ self.text += "\n{}".format(comment)
+
+ # show relationships
+ relationships = self.get_data("relationships")
+ if ((not tag) and self.with_rel and relationships):
+ for d in relationships:
+ self.make_full(self.get_item(d.keys()),
+ self.get_related_file(self.get_item(d.values())))
+
+ #--------------------
+ # show
+ #--------------------
+ def show(self):
+ for f in self.files:
+ if (self.one_line):
+ self.make_one(None, f)
+ else:
+ self.make_full(None, f)
+
+ # escape " -> \"
+ # otherwise " will be disappeared
+ self.text = self.text.replace("\"", "\\\"");
+ self.do("echo \"{}\" | {}".format(
+ self.text, self.config("viewer")))
+
+#====================================
+#
+# As command
+#
+#====================================
+if __name__=='__main__':
+ viewer(sys.argv).show()