ptf 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,58 +7,54 @@ module Ptf
7
7
  class << self
8
8
 
9
9
  def show(id)
10
- if !Ptf::Utilities::FileSystem.id_exist?(id.to_i)
11
- puts "Task #{id} does not exist."
12
- return
10
+ if !Ptf::FileSystem.id_exist?(id.to_i)
11
+ return "Task #{id} does not exist."
13
12
  end
14
13
 
15
- metadata_file = Ptf::Utilities::FileSystem.find_file id.to_i
14
+ metadata_file = Ptf::FileSystem.find_file id.to_i
16
15
 
17
16
  if metadata_file.nil?
18
- puts "Task #{id} has been closed. Reopen it with ptf task reopen ###."
19
- return
17
+ return "Task #{id} has been closed. Reopen it with ptf task reopen ###."
20
18
  end
21
19
 
22
- info = Ptf::Data::MetadataFile.new(metadata_file)
20
+ info = Ptf::MetadataFile.create_from_file(metadata_file)
23
21
 
24
- data_file = File.join(Ptf::Utilities::FileSystem.data_dir, info.hash)
25
- puts `cat #{data_file}`
22
+ data_file = File.join(Ptf::FileSystem.data_dir, info.hash)
23
+ return File.read data_file
26
24
  end
27
25
 
28
26
  def close(id)
29
- if !Ptf::Utilities::FileSystem.id_exist?(id.to_i)
30
- puts "Task #{id} does not exist."
31
- return
27
+ if !Ptf::FileSystem.id_exist?(id.to_i)
28
+ return "Task #{id} does not exist."
32
29
  end
33
30
 
34
- metadata_file = Ptf::Utilities::FileSystem.find_file id.to_i
31
+ metadata_file = Ptf::FileSystem.find_file id.to_i
35
32
 
36
33
  if metadata_file.nil?
37
- puts "Task #{id} has been closed. Reopen it with ptf task reopen ###."
38
- return
34
+ return "Task #{id} has been closed. Reopen it with ptf task reopen ###."
39
35
  end
40
36
 
41
- info = Ptf::Data::MetadataFile.create_from_file(metadata_file)
37
+ info = Ptf::MetadataFile.create_from_file(metadata_file)
42
38
 
43
39
  info.complete_now
40
+ return "Task #{info.id} is closed."
44
41
  end
45
42
 
46
43
  def reopen(id)
47
- if !Ptf::Utilities::FileSystem.id_exist?(id.to_i)
48
- puts "Task #{id} does not exist."
49
- return
44
+ if !Ptf::FileSystem.id_exist?(id.to_i)
45
+ return "Task #{id} does not exist."
50
46
  end
51
47
 
52
- metadata_file = Ptf::Utilities::FileSystem.find_file id.to_i, false
48
+ metadata_file = Ptf::FileSystem.find_file id.to_i, false
53
49
 
54
50
  if metadata_file.nil?
55
- puts "Task #{id} is already open. Close it with ptf task close ###."
56
- return
51
+ return "Task #{id} is already open. Close it with ptf task close ###."
57
52
  end
58
53
 
59
- info = Ptf::Data::MetadataFile.create_from_file(metadata_file)
54
+ info = Ptf::MetadataFile.create_from_file(metadata_file)
60
55
 
61
56
  info.reopen
57
+ return "Task #{info.id} is reopened."
62
58
  end
63
59
 
64
60
  end
@@ -11,7 +11,7 @@ module Ptf
11
11
  end
12
12
 
13
13
  def new_id_number
14
- id_file_path = Ptf::Utilities::FileSystem.id_counter_file
14
+ id_file_path = Ptf::FileSystem.id_counter_file
15
15
  next_id = File.read(id_file_path).to_i
16
16
 
17
17
  id_file = File.new(id_file_path, "w")
@@ -29,38 +29,38 @@ module Ptf
29
29
 
30
30
  # Select a group for the task
31
31
  if group.nil?
32
- group = Ptf::Data::Group.default_group
32
+ group = Ptf::Group.default_group
33
33
  else
34
- if Ptf::Data::Group.group_exist? group
35
- group = Ptf::Data::Group.get_group group
34
+ if Ptf::Group.group_exist? group
35
+ group = Ptf::Group.get_group group
36
36
  else
37
- puts "Group #{p} does not exist. Create it with ptf group add GROUP ABBREVIATION"
38
- return
37
+ return "Group #{p} does not exist. Create it with ptf group add GROUP ABBREVIATION"
39
38
  end
40
39
  end
41
40
 
42
41
  # Verify the due date
43
42
  if !due_date.nil?
44
- due_date = Ptf::Utilities::Date.create_datetime_from_str(due_date)
43
+ due_date = Ptf::Date.create_datetime_from_str(due_date)
45
44
  if due_date.nil?
46
- puts "Improperly formatted due date '#{d}' given."
47
- return
45
+ return "Improperly formatted due date '#{d}' given."
48
46
  end
49
47
  end
50
48
 
51
49
  id = new_id_number
52
50
 
53
- info_file = Ptf::Data::MetadataFile.create_from_input(title, group, due_date, estimate, id)
51
+ info_file = Ptf::MetadataFile.create_from_input(title, group, due_date, estimate, id)
54
52
 
55
53
  task_info_hash = generate_hash info_file.file_string
56
54
 
57
55
  # Append hash to the file
58
56
  info_file.add_content(:hash, task_info_hash)
59
57
 
60
- data_file = Ptf::Data::DataFile.new(info_file)
58
+ data_file = Ptf::DataFile.new(info_file)
61
59
 
62
60
  info_file.write_to_file
63
61
  data_file.write_to_file
62
+
63
+ return "Task #{info_file.id} created successfully."
64
64
  end
65
65
 
66
66
  end
@@ -4,47 +4,131 @@ module Ptf
4
4
  module Edit
5
5
  class << self
6
6
 
7
- def verify_file(file)
8
- puts "File verification not implemented"
9
- true
7
+ def verify_file(file, metadata)
8
+ title_line, due_date_line, estimate_line = File.foreach(file).first(3)
9
+
10
+ did_succeed, updated_metadata = verify_title_line title_line, metadata
11
+ return false unless did_succeed
12
+
13
+ did_succeed, updated_metadata = verify_due due_date_line, updated_metadata
14
+ return false unless did_succeed
15
+
16
+ did_succeed, updated_metadata = verify_estimate estimate_line, updated_metadata
17
+ return false unless did_succeed
18
+
19
+ updated_metadata.write_to_file
20
+ did_succeed
21
+ end
22
+
23
+ def verify_title_line(line, metadata)
24
+ title_line_regex = /^#([A-Z]+)--(\d+)\s([ a-zA-Z0-9]+)$/
25
+
26
+ _, group, id, title = title_line_regex.match(line).to_a
27
+
28
+ is_title_valid, updated_metadata = verify_title title, metadata
29
+ [(verify_group group, metadata) && (verify_id id, metadata) && is_title_valid, updated_metadata]
30
+ end
31
+
32
+ def verify_group(str, metadata)
33
+ return false unless !str.nil? && str.is_a?(String)
34
+
35
+ Ptf::Group.group_exist?(str) && metadata.group.abbreviation == str
36
+ end
37
+
38
+ def verify_id(str, metadata)
39
+ return false unless !str.nil? && str.is_a?(String)
40
+
41
+ str.to_i == metadata.id
42
+ end
43
+
44
+ def verify_title(str, metadata)
45
+ return false unless !str.nil? && str.is_a?(String)
46
+
47
+ if str != metadata.title
48
+ metadata.set_title str
49
+ end
50
+
51
+ [true, metadata]
52
+ end
53
+
54
+ def verify_due(line, metadata)
55
+ due_line_regex = /^#Due: ?(\d\d\d\d[01]\d[0-3]\d[0-2]\d[0-5]\d[0-5]\d)?$/
56
+
57
+ base, date = due_line_regex.match(line).to_a
58
+
59
+ if !base.nil? && date.nil?
60
+ metadata.set_due_date nil
61
+ return [true, metadata]
62
+ end
63
+
64
+ begin
65
+ datetime = Ptf::Date.str_to_datetime date
66
+ rescue
67
+ return [false, metadata]
68
+ end
69
+
70
+ metadata.set_due_date datetime
71
+ [!datetime.nil?, metadata]
72
+ end
73
+
74
+ def verify_estimate(line, metadata)
75
+ estimate_line_regex = /^#Estimate: ?(\d+)?$/
76
+
77
+ base, estimate = estimate_line_regex.match(line).to_a
78
+
79
+ if !base.nil? && estimate.nil?
80
+ metadata.set_estimate nil
81
+ return [true, metadata]
82
+ elsif base.nil?
83
+ return [false, metadata]
84
+ end
85
+
86
+ estimate = estimate.to_i
87
+ if estimate != 0
88
+ metadata.set_estimate estimate
89
+ return [true, metadata]
90
+ else
91
+ return [false, metadata]
92
+ end
10
93
  end
11
94
 
12
95
  def edit(id)
13
- unless Ptf::Utilities::FileSystem.id_exist? (id)
14
- puts "The task #{id} does not exist"
15
- return
96
+ unless Ptf::FileSystem.id_exist? (id)
97
+ return "The task #{id} does not exist"
16
98
  end
17
99
 
18
- metadata_file = Ptf::Utilities::FileSystem.find_file id
100
+ metadata_file = Ptf::FileSystem.find_file id
19
101
 
20
102
  if metadata_file.nil?
21
- puts "The task #{id} has been closed. Reopen it with ptf task reopen ###."
22
- return
103
+ return "The task #{id} has been closed. Reopen it with ptf task reopen ###."
23
104
  end
24
105
 
25
106
  # Get hash from file
26
- data_file_name = Ptf::Data::MetadataFile.create_from_file(metadata_file).hash
27
- data_file = File.join(Ptf::Utilities::FileSystem.data_dir, data_file_name)
107
+ metadata = Ptf::MetadataFile.create_from_file(metadata_file)
108
+ data_file_name = metadata.hash
109
+ data_file = File.join(Ptf::FileSystem.data_dir, data_file_name)
28
110
 
29
111
  # Create a copy in tmp foldere
30
- tmp_file_path = File.join(Ptf::Utilities::FileSystem.tmp_dir, data_file_name)
112
+ tmp_file_path = File.join(Ptf::FileSystem.tmp_dir, data_file_name)
31
113
  FileUtils.copy data_file, tmp_file_path
32
114
  edit_succeeded = system("vim #{data_file}")
33
115
 
34
116
  if !edit_succeeded
35
117
  # Move tmp file back, then remove it
36
- puts "Vim edit failed. Aborting changes."
37
- return
118
+
119
+ FileUtils.copy tmp_file_path, data_file
120
+ FileUtils.remove_file tmp_file_path
121
+ return "Vim edit failed. Aborting changes."
38
122
  end
39
123
 
40
- if verify_file(data_file)
41
- puts "Edit successful!"
124
+ if verify_file(data_file, metadata)
125
+ FileUtils.remove_file tmp_file_path
126
+ return "Edit successful!"
42
127
  else
43
- puts "File verification failed. Aborting changes."
128
+ FileUtils.copy tmp_file_path, data_file
129
+ FileUtils.remove_file tmp_file_path
130
+ return "File verification failed. Aborting changes."
44
131
  end
45
-
46
- # remove tmp file
47
- FileUtils.remove_file tmp_file_path
48
132
  end
49
133
 
50
134
  end
@@ -0,0 +1,40 @@
1
+ module Ptf
2
+ class DataFile
3
+
4
+ DIR_PATH = Ptf::FileSystem.data_dir
5
+
6
+ # Initialize a new DataFile.
7
+ #
8
+ # @param metadata_file [Ptf::MetadataFile] the associated metadata file.
9
+ #
10
+ # @raise [ArgumntError] if a MetadataFile is not given.
11
+ def initialize(metadata_file)
12
+ raise ArgumentError, "Metadata file not given." unless metadata_file.is_a? Ptf::MetadataFile
13
+
14
+ @metadata_file = metadata_file
15
+ end
16
+
17
+ # Returns the full path to the data file.
18
+ #
19
+ # @return [String] the full path to the data file.
20
+ def data_file_path
21
+ File.join(DIR_PATH, @metadata_file.hash)
22
+ end
23
+
24
+ # Returns the header string for the file.
25
+ #
26
+ # @return [String] the header string for the data file.
27
+ def header_string
28
+ "##{@metadata_file.group.abbreviation}--#{@metadata_file.id} #{@metadata_file.title}\n#Due: #{@metadata_file.due_date_str}\n#Estimate: #{@metadata_file.estimate}\n\n\n"
29
+ end
30
+
31
+ # Write the header string to the data file. Overwrites any data file for the same task.
32
+ def write_to_file
33
+ File.open(data_file_path, "w") do |f|
34
+ f.write header_string
35
+ end
36
+ end
37
+
38
+ end
39
+ end
40
+
@@ -0,0 +1,61 @@
1
+ module Ptf
2
+ module Date
3
+ class << self
4
+
5
+ def datetime_to_str(datetime)
6
+ raise ArgumentError, "DateTime expected. Received #{datetime.class} instead." unless datetime.is_a? DateTime
7
+
8
+ datetime.strftime('%Y%m%d%H%M%S')
9
+ end
10
+
11
+ def create_datetime_from_str(str)
12
+
13
+ begin
14
+ dt = str_to_datetime(str)
15
+ return dt
16
+ rescue
17
+ end
18
+
19
+ time_regex = /([0-2]?\d):([0-5]\d):?([0-5]\d)?/
20
+ # Check if given time 12:21(:21)
21
+ match = time_regex.match(str).to_a
22
+
23
+ if !match.nil? && (match.length == 3 || match.length == 4)
24
+ now = DateTime.now
25
+ return DateTime.new(now.year, now.month, now.day, match[1].to_i, match[2].to_i, 0, now.zone)
26
+ end
27
+
28
+ # Check if given date 12/27(/[15|2015])
29
+ date_regex = /^([01]?\d)\/([0-3]?\d)\/?(\d\d\d\d|\d\d)?$/
30
+ match = date_regex.match(str)
31
+
32
+ if !match.nil? && (match.length == 3 || match.length == 4)
33
+ now = DateTime.now
34
+
35
+ if !match[3].nil? && match[3].length == 2
36
+ year = 2000 + match[3].to_i
37
+ elsif !match[3].nil?
38
+ year = match[3].to_i
39
+ end
40
+
41
+ return DateTime.new((match[3].nil? ? now.year : year), match[1].to_i, match[2].to_i, 12, 0, 0, now.zone)
42
+ end
43
+
44
+ nil
45
+ end
46
+
47
+ def str_to_datetime(str)
48
+ date_regex = /^(\d\d\d\d)([01]\d)([0-3]\d)([0-2]\d)([0-5]\d)([0-5]\d)?$/
49
+
50
+ regex_match = date_regex.match(str)
51
+
52
+ raise ArgumentError, "Improperly formatted datetime string, #{str}." unless regex_match.to_a.length == 7
53
+
54
+ _, year, month, day, hour, minute, second = regex_match.to_a
55
+
56
+ DateTime.new(year.to_i, month.to_i, day.to_i, hour.to_i, minute.to_i, second.to_i)
57
+ end
58
+
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,81 @@
1
+ module Ptf
2
+ module FileSystem
3
+ class << self
4
+
5
+ def file_exist?(filepath)
6
+ File.file?(filepath)
7
+ end
8
+
9
+ def config
10
+ @config = Ptf::Config.get_config if @config.nil?
11
+
12
+ @config
13
+ end
14
+
15
+ def file_permission
16
+ @config[:file_permission]
17
+ end
18
+
19
+ def base_dir
20
+ config[:base_dir]
21
+ end
22
+
23
+ def id_counter_file
24
+ File.join(base_dir, config[:task_counter_file])
25
+ end
26
+
27
+ def id_counter_starting_content
28
+ config[:id_counter_start]
29
+ end
30
+
31
+ def group_list_file
32
+ File.join(base_dir, config[:group_list_file])
33
+ end
34
+
35
+ def metadata_dir
36
+ File.join(base_dir, config[:task_metadata_dir])
37
+ end
38
+
39
+ def metadata_open_dir
40
+ File.join(metadata_dir, config[:in_progress_dir])
41
+ end
42
+
43
+ def metadata_closed_dir
44
+ File.join(metadata_dir, config[:completed_dir])
45
+ end
46
+
47
+ def data_dir
48
+ File.join(base_dir, config[:task_data_dir])
49
+ end
50
+
51
+ def tmp_dir
52
+ File.join(base_dir, config[:tmp_dir])
53
+ end
54
+
55
+ def id_exist?(id)
56
+ next_id = File.read(id_counter_file).to_i
57
+
58
+ (id < next_id && id > 0)
59
+ end
60
+
61
+ def find_file(id, open = true)
62
+ raise ArgumentError, "No task with id #{id} exists." unless id_exist?(id)
63
+
64
+ search_dir = (open ? metadata_open_dir : metadata_closed_dir)
65
+ groups = Ptf::Group.all_groups
66
+
67
+ groups.each do |g|
68
+ dir = File.join(search_dir, g.name)
69
+ possible_id_file = File.join(dir, id.to_s)
70
+
71
+ if file_exist?(possible_id_file)
72
+ return possible_id_file
73
+ end
74
+ end
75
+
76
+ nil
77
+ end
78
+
79
+ end
80
+ end
81
+ end