mirror of
https://github.com/michaeldv/pit.git
synced 2025-12-09 16:05:35 +00:00
Created first project saving it and reading from .pit file!
This commit is contained in:
26
src/activity.c
Normal file
26
src/activity.c
Normal file
@@ -0,0 +1,26 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include "pit.h"
|
||||
#include "activity.h"
|
||||
|
||||
ulong subject_id; /* Reference to the specific Project, Task, or Note. */
|
||||
char subject[16]; /* Project, Task, or Note. */
|
||||
char message[255]; /* Log message. */
|
||||
ulong created_by; /* Who added log message? */
|
||||
time_t created_at; /* When log message was added? */
|
||||
|
||||
PActivity pit_add_activity(ulong id, char *subject, char *message, ulong user_id) {
|
||||
static Activity activity;
|
||||
|
||||
memset(&activity, 0, sizeof(activity));
|
||||
|
||||
activity.subject_id = id;
|
||||
activity.created_by = user_id;
|
||||
activity.created_at = time(NULL);
|
||||
strncpy(activity.subject, subject, sizeof(activity.subject) - 1);
|
||||
strncpy(activity.message, message, sizeof(activity.message) - 1);
|
||||
|
||||
return &activity;
|
||||
}
|
||||
1
src/activity.h
Normal file
1
src/activity.h
Normal file
@@ -0,0 +1 @@
|
||||
PActivity pit_add_activity(ulong id, char *subject, char *message, ulong user_id);
|
||||
BIN
src/activity.o
Normal file
BIN
src/activity.o
Normal file
Binary file not shown.
54
src/db.c
Normal file
54
src/db.c
Normal file
@@ -0,0 +1,54 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include "pit.h"
|
||||
#include "db.h"
|
||||
#include "activity.h"
|
||||
#include "user.h"
|
||||
|
||||
#define PITFILE "/tmp/.pit"
|
||||
|
||||
void pit_db_load() {
|
||||
FILE *pitfile = fopen(PITFILE, "r");
|
||||
|
||||
if (pitfile) {
|
||||
projects = pit_table_load(pitfile);
|
||||
tasks = pit_table_load(pitfile);
|
||||
notes = pit_table_load(pitfile);
|
||||
activities = pit_table_load(pitfile);
|
||||
users = pit_table_load(pitfile);
|
||||
fclose(pitfile);
|
||||
} else {
|
||||
pit_db_initialize();
|
||||
}
|
||||
}
|
||||
|
||||
void pit_db_initialize() {
|
||||
projects = pit_table_initialize(sizeof(Project), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS);
|
||||
tasks = pit_table_initialize(sizeof(Task), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS);
|
||||
notes = pit_table_initialize(sizeof(Note), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS);
|
||||
activities = pit_table_initialize(sizeof(Activity), TABLE_HAS_CREATED_AT);
|
||||
users = pit_table_initialize(sizeof(User), TABLE_HAS_ID);
|
||||
|
||||
pit_table_insert(users, (uchar *)pit_current_user());
|
||||
pit_table_insert(activities, (uchar *)pit_add_activity(0, "", "Initialized pit", 1));
|
||||
|
||||
pit_db_save();
|
||||
}
|
||||
|
||||
void pit_db_save() {
|
||||
FILE *pitfile = fopen(PITFILE, "wb");
|
||||
|
||||
if (!pitfile) {
|
||||
die_with_errno(PITFILE);
|
||||
} else {
|
||||
pit_table_save(pitfile, projects);
|
||||
pit_table_save(pitfile, tasks);
|
||||
pit_table_save(pitfile, notes);
|
||||
pit_table_save(pitfile, activities);
|
||||
pit_table_save(pitfile, users);
|
||||
|
||||
fclose(pitfile);
|
||||
}
|
||||
}
|
||||
7
src/db.h
Normal file
7
src/db.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#if !defined(__DB_H__)
|
||||
#define __DB_H__
|
||||
|
||||
void pit_db_load();
|
||||
void pit_db_save();
|
||||
void pit_db_initialize();
|
||||
#endif
|
||||
26
src/pit.c
26
src/pit.c
@@ -1,21 +1,45 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include "pit.h"
|
||||
#include "project.h"
|
||||
#include "task.h"
|
||||
|
||||
PTable projects;
|
||||
PTable tasks;
|
||||
PTable notes;
|
||||
PTable activities;
|
||||
PTable users;
|
||||
|
||||
static int usage() {
|
||||
printf("usage...\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void die(char *msg)
|
||||
{
|
||||
fprintf(stderr, "pit (fatal): %s\n", msg);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void die_with_errno(char *prefix)
|
||||
{
|
||||
fprintf(stderr, "pit (fatal): %s: ", prefix);
|
||||
perror(NULL);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int i;
|
||||
char *commands[] = { "project", "task", "note", "log" };
|
||||
|
||||
/***
|
||||
int i;
|
||||
printf("argc: %d\n", argc);
|
||||
for(i = 0; i < argc; i++) {
|
||||
printf("argv[%d]: [%s]\n", i, argv[i]);
|
||||
}
|
||||
***/
|
||||
|
||||
if (argc > 1) {
|
||||
if (strstr(commands[0], argv[1]) == commands[0]) {
|
||||
|
||||
69
src/pit.h
69
src/pit.h
@@ -1,10 +1,75 @@
|
||||
#if !defined(__PIT_H__)
|
||||
#define __PIT_H__
|
||||
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned long ulong;
|
||||
typedef unsigned char uchar;
|
||||
|
||||
int pit_project(char *argv[]);
|
||||
int pit_task(char *argv[]);
|
||||
#include "table.h"
|
||||
|
||||
typedef struct {
|
||||
ulong id;
|
||||
int current; /* 1 if the project is current, 0 otherwise. */
|
||||
char name[128]; /* Project name. */
|
||||
char status[16]; /* Project status. */
|
||||
ulong number_of_open_tasks; /* Number of open tasks. */
|
||||
ulong number_of_closed_tasks; /* Number of closed tasks. */
|
||||
ulong closed_by; /* Who closed the project? */
|
||||
ulong created_by; /* Who created the project? */
|
||||
ulong updated_by; /* Who last updated the project? */
|
||||
time_t closed_at; /* When the project was closed? */
|
||||
time_t created_at; /* When the project was created? */
|
||||
time_t updated_at; /* When the project was last updated? */
|
||||
} Project, *PProject;
|
||||
|
||||
typedef struct {
|
||||
ulong id;
|
||||
ulong project_id; /* Which project the task belongs to? */
|
||||
int current; /* 1 if the task is current, 0 otherwise. */
|
||||
int priority; /* Task priority. */
|
||||
char name[128]; /* Task name. */
|
||||
char status[16]; /* Task status. */
|
||||
time_t deadline; /* Task deadline. */
|
||||
ulong number_of_notes; /* Number of notes. */
|
||||
ulong closed_by; /* Who closed the task? */
|
||||
ulong created_by; /* Who created the task? */
|
||||
ulong updated_by; /* Who last updated the task? */
|
||||
time_t closed_at; /* When the task was closed? */
|
||||
time_t created_at; /* When the task was created? */
|
||||
time_t updated_at; /* When the task was last updated? */
|
||||
} Task, *PTask;
|
||||
|
||||
typedef struct {
|
||||
ulong id;
|
||||
ulong task_id; /* Task the note belongs to. */
|
||||
char message[255]; /* The body of the note. */
|
||||
ulong created_by; /* Who created the note? */
|
||||
ulong updated_by; /* Who last updated the note? */
|
||||
time_t created_at; /* When the note was created? */
|
||||
time_t updated_at; /* When the note was last updated? */
|
||||
} Note, *PNote;
|
||||
|
||||
typedef struct {
|
||||
ulong subject_id; /* Reference to the specific Project, Task, or Note. */
|
||||
char subject[16]; /* Project, Task, or Note. */
|
||||
char message[255]; /* Log message. */
|
||||
ulong created_by; /* Who added log message? */
|
||||
time_t created_at; /* When log message was added? */
|
||||
} Activity, *PActivity;
|
||||
|
||||
typedef struct {
|
||||
ulong id;
|
||||
char username[32]; /* Username. */
|
||||
char email[32]; /* User's email. */
|
||||
} User, *PUser;
|
||||
|
||||
extern PTable projects;
|
||||
extern PTable tasks;
|
||||
extern PTable notes;
|
||||
extern PTable activities;
|
||||
extern PTable users;
|
||||
|
||||
void die(char *msg);
|
||||
void die_with_errno(char *prefix);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,15 +1,79 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include "pit.h"
|
||||
#include "db.h"
|
||||
#include "project.h"
|
||||
|
||||
int pit_project(char *argv[]) {
|
||||
static int already_exist(char *name)
|
||||
{
|
||||
ulong i;
|
||||
PProject pp;
|
||||
|
||||
pit_db_load();
|
||||
for(i = 0, pp = (PProject)projects->slots; i < projects->number_of_records; i++, pp++) {
|
||||
if (!strcmp(pp->name, name)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void list_projects()
|
||||
{
|
||||
ulong i;
|
||||
PProject pp;
|
||||
|
||||
pit_db_load();
|
||||
for(i = 0, pp = (PProject)projects->slots; i < projects->number_of_records; i++, pp++) {
|
||||
printf("%lu: [%s] %s\n", pp->id, pp->status, pp->name);
|
||||
}
|
||||
}
|
||||
|
||||
static void create_project(char *name, char *status)
|
||||
{
|
||||
pit_db_load();
|
||||
printf("creating project [%s], status [%s]\n", name, status);
|
||||
|
||||
if (!already_exist(name)) {
|
||||
Project p;
|
||||
|
||||
memset(&p, 0, sizeof(p));
|
||||
|
||||
strncpy(p.name, name, sizeof(p.name) - 1);
|
||||
strncpy(p.status, status, sizeof(p.status) - 1);
|
||||
p.current = 1;
|
||||
p.number_of_open_tasks = 0;
|
||||
p.number_of_closed_tasks = 0;
|
||||
p.closed_by = 0;
|
||||
p.created_by = p.updated_by = 1; // TODO
|
||||
p.closed_at = 0;
|
||||
p.created_at = p.updated_at = time(NULL);
|
||||
pit_table_insert(projects, (uchar *)&p);
|
||||
pit_db_save();
|
||||
}
|
||||
}
|
||||
|
||||
static int show_project(unsigned long number)
|
||||
{
|
||||
printf("showing project %lu\n", number);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int delete_project(unsigned long number)
|
||||
{
|
||||
printf("deleting project %lu\n", number);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pit_project(char *argv[])
|
||||
{
|
||||
char **arg = &argv[1];
|
||||
char *error = NULL;
|
||||
|
||||
if (!*arg) {
|
||||
printf("list projects\n");
|
||||
list_projects();
|
||||
} else if (!strcmp(*arg, "-c")) {
|
||||
if (!*++arg) {
|
||||
error = "missing project name";
|
||||
@@ -39,19 +103,3 @@ int pit_project(char *argv[]) {
|
||||
|
||||
return error == NULL;
|
||||
}
|
||||
|
||||
static int create_project(char *name, char *status) {
|
||||
printf("creating project [%s], status [%s]\n", name, status);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int show_project(unsigned long number) {
|
||||
printf("showing project %lu\n", number);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int delete_project(unsigned long number) {
|
||||
printf("deleting project %lu\n", number);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#if !defined(__PROJECT_H__)
|
||||
#define __PROJECT_H__
|
||||
|
||||
static int create_project(char *name, char *status);
|
||||
static int show_project(unsigned long number);
|
||||
static int delete_project(unsigned long number);
|
||||
int pit_project(char *argv[]);
|
||||
|
||||
#endif
|
||||
|
||||
43
src/table.c
43
src/table.c
@@ -3,22 +3,16 @@
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "pit.h"
|
||||
#include "table.h"
|
||||
|
||||
#define TABLE_INCREMENT 5
|
||||
#define TABLE_HAS_ID 1
|
||||
#define TABLE_HAS_CREATED_AT 2
|
||||
#define TABLE_HAS_UPDATED_AT 4
|
||||
#define TABLE_HAS_TIMESTAMPS (TABLE_HAS_CREATED_AT | TABLE_HAS_UPDATED_AT)
|
||||
|
||||
/*
|
||||
** Initialize the table by alloocating necessary memory chunks.
|
||||
*/
|
||||
PTable table_initialize(ulong record_size, ulong flags) {
|
||||
PTable pit_table_initialize(ulong record_size, ulong flags) {
|
||||
PTable pt;
|
||||
|
||||
pt = calloc(1, sizeof(Table));
|
||||
pt->flags = flags | TABLE_HAS_ID;
|
||||
pt->flags = flags;
|
||||
pt->record_size = record_size;
|
||||
pt->number_of_slots = TABLE_INCREMENT;
|
||||
pt->number_of_records = 0;
|
||||
@@ -100,7 +94,8 @@ static PTable table_extend(PTable pt) {
|
||||
/*
|
||||
** Find a record by id and return its address.
|
||||
*/
|
||||
uchar *table_find(PTable pt, ulong id) {
|
||||
uchar *pit_table_find(PTable pt, ulong id) {
|
||||
// TODO: retrn NULL (or raise?) if table doesn't have id.
|
||||
if (pt->number_of_records == 0 || id <= 0 || id > pt->auto_increment) {
|
||||
return NULL;
|
||||
} else {
|
||||
@@ -112,8 +107,9 @@ uchar *table_find(PTable pt, ulong id) {
|
||||
** Delete a record by its ID. Return the address of next record or NULL
|
||||
** if deleted last record.
|
||||
*/
|
||||
uchar *table_delete(PTable pt, ulong id) {
|
||||
register uchar *pr = (uchar *)table_find(pt, id);
|
||||
uchar *pit_table_delete(PTable pt, ulong id) {
|
||||
// TODO: retrn NULL (or raise?) if table doesn't have id.
|
||||
register uchar *pr = (uchar *)pit_table_find(pt, id);
|
||||
|
||||
if (pr) {
|
||||
register ulong i;
|
||||
@@ -153,7 +149,7 @@ uchar *table_delete(PTable pt, ulong id) {
|
||||
** Insert a record and return its address. The table gets extended
|
||||
** as necessary.
|
||||
*/
|
||||
uchar *table_insert(PTable pt, uchar *record) {
|
||||
uchar *pit_table_insert(PTable pt, uchar *record) {
|
||||
register uchar **pi;
|
||||
register time_t now;
|
||||
|
||||
@@ -191,7 +187,7 @@ uchar *table_insert(PTable pt, uchar *record) {
|
||||
/*
|
||||
** Release pt->slots and pt->index memory chunks, then free the table itself.
|
||||
*/
|
||||
PTable table_free(PTable pt) {
|
||||
PTable pit_table_free(PTable pt) {
|
||||
if (pt) {
|
||||
if (pt->index) {
|
||||
free(pt->index);
|
||||
@@ -209,7 +205,7 @@ PTable table_free(PTable pt) {
|
||||
** Save the contents of the table to file. The file handle should be
|
||||
** open with for writing.
|
||||
*/
|
||||
int table_save(FILE *file, PTable pt) {
|
||||
int pit_table_save(FILE *file, PTable pt) {
|
||||
register int written = 0;
|
||||
/*
|
||||
** Save table header data: flags, record_size, number_of_slots,
|
||||
@@ -227,7 +223,7 @@ int table_save(FILE *file, PTable pt) {
|
||||
** Load the contents of the table from file. The file handle should be
|
||||
** open with for reading.
|
||||
*/
|
||||
PTable table_load(FILE *file) {
|
||||
PTable pit_table_load(FILE *file) {
|
||||
PTable pt;
|
||||
register int read = 0;
|
||||
register ulong i;
|
||||
@@ -241,7 +237,7 @@ PTable table_load(FILE *file) {
|
||||
/*
|
||||
** Now allocate slots and index based n original number of slots.
|
||||
*/
|
||||
printf("Allocating %lu slots\n", pt->number_of_slots);
|
||||
/*** printf("Allocating %lu slots\n", pt->number_of_slots); ***/
|
||||
pt->slots = pr = calloc(pt->number_of_slots, pt->record_size);
|
||||
pt->index = pi = calloc(pt->number_of_slots, sizeof(uchar *));
|
||||
/*
|
||||
@@ -249,6 +245,7 @@ PTable table_load(FILE *file) {
|
||||
*/
|
||||
read += fread(pt->slots, pt->record_size, pt->number_of_records, file);
|
||||
for(i = 0; i < pt->number_of_records; i++, pi++) {
|
||||
// TODO: if table doesn't have id || has id && id matches...
|
||||
if ((ulong)*pr == i + 1) {
|
||||
*pi = pr;
|
||||
pr += pt->record_size;
|
||||
@@ -283,7 +280,7 @@ void dump_all(PTable pt) {
|
||||
Record *prec;
|
||||
|
||||
for(i = 1; i <= pt->number_of_slots; i++) {
|
||||
prec = (Record *)table_find(pt, i);
|
||||
prec = (Record *)pit_table_find(pt, i);
|
||||
if (prec) {
|
||||
dump(prec);
|
||||
} else {
|
||||
@@ -298,32 +295,32 @@ int main() {
|
||||
Record rec, *prec;
|
||||
ulong i, total = 30;
|
||||
|
||||
pt = table_initialize(sizeof(Record), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS);
|
||||
pt = pit_table_initialize(sizeof(Record), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS);
|
||||
for(i = 0; i < total; i++) {
|
||||
rec.id = 0;
|
||||
rec.value = 0x11223344 + i + 1;
|
||||
strcpy(rec.name, "test");
|
||||
rec.created_at = rec.updated_at = (time_t)0;
|
||||
|
||||
prec = (Record *)table_insert(pt, (uchar *)&rec);
|
||||
prec = (Record *)pit_table_insert(pt, (uchar *)&rec);
|
||||
dump(prec);
|
||||
}
|
||||
for (i = 20; i < total; i++) {
|
||||
printf("Deleting %lu\n", i + 1);
|
||||
prec = (Record *)table_delete(pt, i + 1);
|
||||
prec = (Record *)pit_table_delete(pt, i + 1);
|
||||
}
|
||||
dump_all(pt);
|
||||
|
||||
FILE *file = fopen("/tmp/.pit", "w");
|
||||
table_save(file, pt);
|
||||
pit_table_save(file, pt);
|
||||
fclose(file);
|
||||
|
||||
file = fopen("/tmp/.pit", "r");
|
||||
pt = table_load(file);
|
||||
pt = pit_table_load(file);
|
||||
dump_all(pt);
|
||||
fclose(file);
|
||||
|
||||
table_free(pt);
|
||||
pit_table_free(pt);
|
||||
printf("OK\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
BIN
src/table.c.out
BIN
src/table.c.out
Binary file not shown.
25
src/table.h
25
src/table.h
@@ -1,6 +1,11 @@
|
||||
#if !defined(__TABLE_H__)
|
||||
#define __TABLE_H__
|
||||
|
||||
#define TABLE_HAS_ID 1
|
||||
#define TABLE_HAS_CREATED_AT 2
|
||||
#define TABLE_HAS_UPDATED_AT 4
|
||||
#define TABLE_HAS_TIMESTAMPS (TABLE_HAS_CREATED_AT | TABLE_HAS_UPDATED_AT)
|
||||
|
||||
typedef struct {
|
||||
ulong flags; /* Bit mask with table flags */
|
||||
ulong record_size; /* Record size in bytes; all records are of fixed size */
|
||||
@@ -11,18 +16,12 @@ typedef struct {
|
||||
uchar **index; /* Memory chunk to store pointers to individual records, holes for deleted record ids */
|
||||
} Table, *PTable;
|
||||
|
||||
PTable table_initialize(ulong record_size, ulong flags);
|
||||
PTable table_free(PTable pt);
|
||||
uchar *table_find(PTable pt, ulong id);
|
||||
uchar *table_delete(PTable pt, ulong id);
|
||||
uchar *table_insert(PTable pt, uchar *record);
|
||||
int table_save(FILE *file, PTable pt);
|
||||
PTable table_load(FILE *file);
|
||||
|
||||
static uchar *table_available_slot(PTable pt);
|
||||
static uchar *table_last_record(PTable pt);
|
||||
static uchar **table_available_index(PTable pt);
|
||||
static uchar **table_last_index(PTable pt);
|
||||
static PTable table_extend(PTable pt);
|
||||
PTable pit_table_initialize(ulong record_size, ulong flags);
|
||||
PTable pit_table_free(PTable pt);
|
||||
uchar *pit_table_find(PTable pt, ulong id);
|
||||
uchar *pit_table_delete(PTable pt, ulong id);
|
||||
uchar *pit_table_insert(PTable pt, uchar *record);
|
||||
int pit_table_save(FILE *file, PTable pt);
|
||||
PTable pit_table_load(FILE *file);
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include "pit.h"
|
||||
#include "task.h"
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#if !defined(__TASK_H__)
|
||||
#define __TASK_H__
|
||||
|
||||
int pit_task(char *argv[]);
|
||||
|
||||
#endif
|
||||
|
||||
11
src/user.c
Normal file
11
src/user.c
Normal file
@@ -0,0 +1,11 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include "pit.h"
|
||||
#include "user.h"
|
||||
|
||||
char *pit_current_user() {
|
||||
return getlogin();
|
||||
}
|
||||
1
src/user.h
Normal file
1
src/user.h
Normal file
@@ -0,0 +1 @@
|
||||
char *pit_current_user();
|
||||
BIN
src/user.o
Normal file
BIN
src/user.o
Normal file
Binary file not shown.
Reference in New Issue
Block a user