parent
0b5c7ce740
commit
5301062b0c
@ -0,0 +1,8 @@
|
|||||||
|
*Compile
|
||||||
|
#do
|
||||||
|
gcc -o tasks tasks.c
|
||||||
|
|
||||||
|
*Test
|
||||||
|
#do
|
||||||
|
./tasks test.tsk
|
||||||
|
|
@ -0,0 +1,160 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import hashlib
|
||||||
|
import pickle
|
||||||
|
from subprocess import run
|
||||||
|
|
||||||
|
tasks = []
|
||||||
|
|
||||||
|
class Task:
|
||||||
|
name = ""
|
||||||
|
ifchange = []
|
||||||
|
commands = []
|
||||||
|
|
||||||
|
def show(self):
|
||||||
|
print(self.name)
|
||||||
|
print(self.ifchange)
|
||||||
|
print(self.commands)
|
||||||
|
|
||||||
|
|
||||||
|
dragon_ascii = """
|
||||||
|
,,
|
||||||
|
`""*$b..
|
||||||
|
""*$o.
|
||||||
|
"$$o.
|
||||||
|
"*$$o.
|
||||||
|
"$$$o.
|
||||||
|
"$$$$bo... ..o:
|
||||||
|
"$$$$$$$$booocS$$$ .. ,.
|
||||||
|
". "*$$$$SP V$o..o$$. .$$$b
|
||||||
|
"$$o. .$$$$$o. ...A$$$$$$$$$$$$$$b
|
||||||
|
""bo. "*$$$$$$$$$$$$$$$$$$$$P*$$$$$$$$:
|
||||||
|
"$$. V$$$$$$$$$P"**""*"' VP * "l
|
||||||
|
"$$$o.4$$$$$$$$X
|
||||||
|
"*$$$$$$$$$$$$$AoA$o..oooooo.. .b
|
||||||
|
.X$$$$$$$$$$$P"" ""*oo,, ,$P
|
||||||
|
$$P""V$$$$$$$: . ""*****"
|
||||||
|
.*" A$$$$$$$$o.4; .
|
||||||
|
.oP"" "$$$$$$b. .$;
|
||||||
|
A$$$$$$$$$$P
|
||||||
|
" "$$$$$P"
|
||||||
|
$$P*"
|
||||||
|
mls .$"
|
||||||
|
"
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
help_message = """
|
||||||
|
tasks :
|
||||||
|
A simple way to define tasks and execute them.
|
||||||
|
|
||||||
|
Usage: tasks file
|
||||||
|
"""
|
||||||
|
def print_help():
|
||||||
|
""" print help and usage """
|
||||||
|
print(dragon_ascii)
|
||||||
|
print(help_message)
|
||||||
|
|
||||||
|
def check_if_file(in_file, check_file):
|
||||||
|
""" Checks it the given file exists, else print error and exit """
|
||||||
|
if os.path.isfile(check_file):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print("In " + in_file + " : " + check_file + " is not a file")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
def getsha1(filename):
|
||||||
|
""" Return the sha1 value of the given filename """
|
||||||
|
with open(filename, 'rb') as file_to_check:
|
||||||
|
data = file_to_check.read()
|
||||||
|
sha1_returned = hashlib.sha1(data).hexdigest()
|
||||||
|
return sha1_returned
|
||||||
|
|
||||||
|
def do_tasks(tasks_file):
|
||||||
|
""" Do the tasks stored in tasks list """
|
||||||
|
stored_entries = {}
|
||||||
|
if os.path.isfile("." + tasks_file + ".bin"):
|
||||||
|
stored_entries = pickle.load(open("." + tasks_file + ".bin", 'rb'))
|
||||||
|
|
||||||
|
for task in tasks:
|
||||||
|
redo_task = False
|
||||||
|
|
||||||
|
""" If change check """
|
||||||
|
for f in task.ifchange:
|
||||||
|
if stored_entries.get(f, "") != getsha1(f):
|
||||||
|
stored_entries[f] = getsha1(f)
|
||||||
|
redo_task = True
|
||||||
|
|
||||||
|
""" Update the stored_entries for this tasks file """
|
||||||
|
pickle.dump(stored_entries, open("." + tasks_file + ".bin", 'wb'))
|
||||||
|
|
||||||
|
if len(task.ifchange) < 1:
|
||||||
|
redo_task = True
|
||||||
|
|
||||||
|
if redo_task == False:
|
||||||
|
continue
|
||||||
|
|
||||||
|
""" Run Commands of the Task """
|
||||||
|
for c in task.commands:
|
||||||
|
print("+ " + c)
|
||||||
|
p = run(c.split())
|
||||||
|
if p.returncode != 0:
|
||||||
|
print(p)
|
||||||
|
print("Task Failed : " + task.name , file=sys.stderr )
|
||||||
|
exit(p.returncode)
|
||||||
|
|
||||||
|
def get_tasks(filename):
|
||||||
|
""" Take a tasks file and convert it to Task structures, stored in a global tasks list """
|
||||||
|
number_of_tasks = 0
|
||||||
|
# Possible sections : comment, ifchange, commands
|
||||||
|
current_section = ""
|
||||||
|
|
||||||
|
with open(filename, 'r') as f:
|
||||||
|
for line in f.readlines():
|
||||||
|
l = line.strip()
|
||||||
|
|
||||||
|
if len(l) > 0 and l[0] == '*':
|
||||||
|
number_of_tasks += 1
|
||||||
|
tasks.append(Task())
|
||||||
|
tasks[number_of_tasks - 1].name = l[1:].strip()
|
||||||
|
tasks[number_of_tasks - 1].ifchange = []
|
||||||
|
tasks[number_of_tasks - 1].commands = []
|
||||||
|
current_section = "comment"
|
||||||
|
continue
|
||||||
|
elif l == "#ifchange":
|
||||||
|
current_section = "ifchange"
|
||||||
|
continue
|
||||||
|
elif l == "#do":
|
||||||
|
current_section = "commands"
|
||||||
|
continue
|
||||||
|
|
||||||
|
if current_section == "ifchange":
|
||||||
|
for entry in l.split():
|
||||||
|
check_if_file(filename, entry)
|
||||||
|
tasks[number_of_tasks - 1].ifchange.append(entry)
|
||||||
|
elif current_section == "commands" and len(l) > 0:
|
||||||
|
tasks[number_of_tasks - 1].commands.append(l)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
tasks_file = "main.tasks"
|
||||||
|
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
if os.path.isfile(sys.argv[1]):
|
||||||
|
tasks_file = sys.argv[1]
|
||||||
|
else:
|
||||||
|
print_help()
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
get_tasks(tasks_file)
|
||||||
|
print("<-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <->")
|
||||||
|
for task in tasks:
|
||||||
|
print("For task named " + task.name)
|
||||||
|
task.show()
|
||||||
|
print("<-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <->")
|
||||||
|
do_tasks(tasks_file)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
pass
|
@ -0,0 +1,255 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define MAX_TASKS 5
|
||||||
|
|
||||||
|
typedef enum {false, true} bool;
|
||||||
|
|
||||||
|
typedef struct TASKS_str_linked_list{
|
||||||
|
char *data;
|
||||||
|
struct TASKS_str_linked_list *next;
|
||||||
|
} TASKS_str_linked_list;
|
||||||
|
|
||||||
|
void TASKS_sll_print(TASKS_str_linked_list *list){
|
||||||
|
printf("[ ");
|
||||||
|
while(list != NULL){
|
||||||
|
printf(" %s ,", list->data);
|
||||||
|
list = list->next;
|
||||||
|
}
|
||||||
|
printf(" ]\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
//* Takes pointer to linked list head *//
|
||||||
|
void TASKS_sll_add(TASKS_str_linked_list **list, char *s){
|
||||||
|
TASKS_str_linked_list *node = (TASKS_str_linked_list *) malloc(sizeof(TASKS_str_linked_list));
|
||||||
|
node->data = s;
|
||||||
|
node->next = *list;
|
||||||
|
*list = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The length values will also count \0
|
||||||
|
typedef struct TASKS_task{
|
||||||
|
char name[100];
|
||||||
|
TASKS_str_linked_list *ifchange;
|
||||||
|
TASKS_str_linked_list *commands;
|
||||||
|
} TASKS_task;
|
||||||
|
|
||||||
|
|
||||||
|
TASKS_task TASKS_new_task(char *name){
|
||||||
|
TASKS_task r;
|
||||||
|
strcpy(r.name, name);
|
||||||
|
r.ifchange = NULL;
|
||||||
|
r.commands = NULL;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TASKS_delete_task(TASKS_task task){
|
||||||
|
// TODO : HERE
|
||||||
|
// This will need to create functions to free TASKS_str_linked_list
|
||||||
|
// For a task ifchange list and commands list needs to be freed
|
||||||
|
// For freeing list, we need to free both strings and the nodes
|
||||||
|
}
|
||||||
|
|
||||||
|
// We currently keeping a global list of tasks.
|
||||||
|
int number_of_tasks = 0;
|
||||||
|
TASKS_task tasks[MAX_TASKS];
|
||||||
|
|
||||||
|
//* Returns the substring from index x to y (both inclusive) *//
|
||||||
|
//* The returned string needs to be freed by the caller of the function *//
|
||||||
|
//* Adds the \0 at end *//
|
||||||
|
char *TASKS_substr(const char *s, int x, int y){
|
||||||
|
assert(y >= x);
|
||||||
|
char *r = (char *) malloc(sizeof(char) * (y - x + 2));
|
||||||
|
|
||||||
|
int j = 0;
|
||||||
|
for(int i = x; i <= y; i++){
|
||||||
|
r[j++] = s[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
r[j] = '\0';
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
//* Checks if file exists by trying to open it *//
|
||||||
|
bool TASKS_file_exists(char *filename){
|
||||||
|
FILE *f = fopen(filename, "r");
|
||||||
|
if(errno == ENOENT)
|
||||||
|
return false;
|
||||||
|
else{
|
||||||
|
fclose(f);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//* Remove white space before and after a line *//
|
||||||
|
//* This function works straight on the pointer, so keep a copy if you need orignal line. *//
|
||||||
|
void TASKS_strip_line(char *line){
|
||||||
|
int len = 0;
|
||||||
|
while(line[len] != '\0') len += 1;
|
||||||
|
|
||||||
|
int start = 0;
|
||||||
|
int end = len;
|
||||||
|
|
||||||
|
for(int i = 0; i < len; i ++){
|
||||||
|
if(line[i] != '\n' && line[i] != '\t' && line[i] != ' ')
|
||||||
|
break;
|
||||||
|
start += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = (len-1); i >= 0; i--){
|
||||||
|
if(line[i] != '\n' && line[i] != '\t' && line[i] != ' ')
|
||||||
|
break;
|
||||||
|
end = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int j = 0;
|
||||||
|
for(int i = start; i <= end; i++)
|
||||||
|
line[j++] = line[i];
|
||||||
|
line[end - start] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
//* Returns true if there are more lines to read, else returns false. *//
|
||||||
|
bool TASKS_get_line(FILE *f, char *line, int *current_line_capacity){
|
||||||
|
if(*current_line_capacity > 1)
|
||||||
|
line[0] = '\0';
|
||||||
|
|
||||||
|
char c;
|
||||||
|
int i = 0;
|
||||||
|
while(true){
|
||||||
|
c = fgetc(f);
|
||||||
|
|
||||||
|
if(c == EOF)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(c == '\n'){
|
||||||
|
line[i] = '\0';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(i > *current_line_capacity){
|
||||||
|
*current_line_capacity *= 2;
|
||||||
|
int x = *current_line_capacity;
|
||||||
|
line = (char *) realloc(line, sizeof(char) * x);
|
||||||
|
}
|
||||||
|
|
||||||
|
line[i++] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TASKS_get_tasks(char *filename){
|
||||||
|
char current_section[10] = "comment";
|
||||||
|
int current_line_capacity = 100;
|
||||||
|
char *current_line = (char *) malloc(sizeof(char) * current_line_capacity);
|
||||||
|
assert(current_line != NULL);
|
||||||
|
|
||||||
|
FILE *f = fopen(filename, "r");
|
||||||
|
assert(f != NULL);
|
||||||
|
|
||||||
|
bool semicolon = true;
|
||||||
|
while(TASKS_get_line(f, current_line, ¤t_line_capacity)){
|
||||||
|
TASKS_strip_line(current_line);
|
||||||
|
|
||||||
|
if(current_line[0] == '\0') continue;
|
||||||
|
|
||||||
|
//* Uncomment to print the file read by program line by line *//
|
||||||
|
//printf("%s\n", current_line);
|
||||||
|
|
||||||
|
// This length includes the \0
|
||||||
|
int current_line_len = 0;
|
||||||
|
while(current_line[current_line_len++] != '\0');
|
||||||
|
|
||||||
|
// Setting current section
|
||||||
|
if(current_line[0] != '\0' && current_line[0] == '*'){
|
||||||
|
number_of_tasks += 1;
|
||||||
|
if(number_of_tasks > MAX_TASKS){
|
||||||
|
printf("MAX_TASKS exceeded, increase the number of max tasks in the source file");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks[number_of_tasks - 1] = TASKS_new_task(TASKS_substr(current_line,1,current_line_len - 1));
|
||||||
|
strcpy(current_section, "comment");
|
||||||
|
continue;
|
||||||
|
}else if(strcmp(current_line, "#ifchange") == 0){
|
||||||
|
strcpy(current_section, "ifchange");
|
||||||
|
continue;
|
||||||
|
}else if(strcmp(current_line, "#do") == 0){
|
||||||
|
strcpy(current_section, "commands");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse file based on current section
|
||||||
|
if(strcmp(current_section, "ifchange") == 0){
|
||||||
|
// TODO : ADD '\ ' to support files with spaces
|
||||||
|
// We use x and y to get substrings from x-y
|
||||||
|
int x = 0;
|
||||||
|
int y = 0;
|
||||||
|
while(current_line[y++] != '\0'){
|
||||||
|
if(current_line[y] == '\n' || current_line[y] == '\t' || current_line[y] == ' '){
|
||||||
|
char *to_add = TASKS_substr(current_line, x, y);
|
||||||
|
TASKS_strip_line(to_add);
|
||||||
|
TASKS_sll_add(&tasks[number_of_tasks - 1].ifchange, to_add);
|
||||||
|
x = y;
|
||||||
|
while(current_line[++y] == '\n' || current_line[y] == '\t' || current_line[y] == ' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
char *to_add = TASKS_substr(current_line, x, y);
|
||||||
|
TASKS_strip_line(to_add);
|
||||||
|
if(to_add[0] == '\0') continue;
|
||||||
|
else TASKS_sll_add(&tasks[number_of_tasks - 1].ifchange, to_add);
|
||||||
|
|
||||||
|
}else if(strcmp(current_section, "commands") == 0){
|
||||||
|
TASKS_sll_add(&tasks[number_of_tasks - 1].commands, TASKS_substr(current_line, 0, current_line_len - 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
free(current_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TASKS_do_all_tasks(){
|
||||||
|
for(int i = 0; i < number_of_tasks; i++){
|
||||||
|
printf("[*] EXECUTING TASK : %s\n", tasks[i].name);
|
||||||
|
TASKS_str_linked_list *cll = tasks[i].commands;
|
||||||
|
while(cll != NULL){
|
||||||
|
char *cmd = cll->data;
|
||||||
|
printf("+ %s\n", cmd);
|
||||||
|
system(cmd);
|
||||||
|
cll = cll->next;
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]){
|
||||||
|
char *tasks_file = "main.tsk";
|
||||||
|
|
||||||
|
if(argc > 1){
|
||||||
|
if(TASKS_file_exists(argv[1]))
|
||||||
|
tasks_file = argv[1];
|
||||||
|
else{
|
||||||
|
/* Print Help Here */
|
||||||
|
printf("File does not exist");
|
||||||
|
exit(ENOENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(TASKS_file_exists(tasks_file));
|
||||||
|
|
||||||
|
printf("Working on tasks file : %s\n", tasks_file);
|
||||||
|
TASKS_get_tasks(tasks_file);
|
||||||
|
|
||||||
|
for(int i = 0; i < number_of_tasks; i++){
|
||||||
|
printf("\n<-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <->\n\n");
|
||||||
|
printf("For task named : %s\n", tasks[i].name);
|
||||||
|
printf("ifchange : "); TASKS_sll_print(tasks[i].ifchange);
|
||||||
|
printf("Commands : "); TASKS_sll_print(tasks[i].commands);
|
||||||
|
}
|
||||||
|
printf("\n<-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <->\n\n");
|
||||||
|
|
||||||
|
//* From here we just need to execute all tasks *//
|
||||||
|
TASKS_do_all_tasks();
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue