1 //
2 //      aegis - project change supervisor
3 //      Copyright (C) 2007, 2008, 2011, 2012 Peter Miller
4 //
5 //      This program is free software; you can redistribute it and/or modify
6 //      it under the terms of the GNU General Public License as published by
7 //      the Free Software Foundation; either version 3 of the License, or
8 //      (at your option) any later version.
9 //
10 //      This program is distributed in the hope that it will be useful,
11 //      but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //      GNU General Public License for more details.
14 //
15 //      You should have received a copy of the GNU General Public License
16 //      along with this program. If not, see
17 //      <http://www.gnu.org/licenses/>.
18 //
19 
20 #include <common/ac/assert.h>
21 
22 #include <common/trace.h>
23 #include <libaegis/gonzo.h>
24 #include <libaegis/lock.h>
25 #include <libaegis/os.h>
26 #include <libaegis/project.h>
27 #include <libaegis/ustate.fmtgen.h>
28 #include <libaegis/user.h>
29 
30 
31 ustate_ty *
ustate_get(project * pp)32 user_ty::ustate_get(project *pp)
33 {
34     trace(("user_ty::ustate_get(this = %p, pp = %p)\n{\n", this,
35         pp));
36     lock_sync();
37     if (!ustate_path)
38     {
39         project *ppp = pp->trunk_get();
40         nstring pn(project_name_get(ppp));
41         ustate_path = gonzo_ustate_path(pn, name());
42     }
43     if (!ustate_data)
44     {
45         gonzo_become();
46         if (os_exists(ustate_path))
47         {
48             ustate_data = ustate_read_file(ustate_path);
49         }
50         else
51         {
52             ustate_data = (ustate_ty *)ustate_type.alloc();
53             ustate_is_new = true;
54         }
55         gonzo_become_undo();
56         if (!ustate_data->own)
57         {
58             ustate_data->own =
59                 (ustate_own_list_ty *)ustate_own_list_type.alloc();
60         }
61     }
62     trace(("return %p;\n", ustate_data));
63     trace(("}\n"));
64     return ustate_data;
65 }
66 
67 
68 void
own_add(project * pp,long change_number)69 user_ty::own_add(project *pp, long change_number)
70 {
71     trace(("user_ty::own_add(this = %p, project_name = \"%s\", "
72         "change_number = %ld)\n{\n", this, project_name_get(pp).c_str(),
73         change_number));
74     ustate_ty *usp = ustate_get(pp);
75     assert(usp->own);
76 
77     //
78     // See if the project is already known.
79     //
80     ustate_own_ty *own_data = 0;
81     size_t j = 0;
82     for (j = 0; j < usp->own->length; ++j)
83     {
84         own_data = usp->own->list[j];
85         if (nstring(own_data->project_name) == project_name_get(pp))
86             break;
87     }
88 
89     //
90     // If the project isn't known, append it to the list.
91     //
92     if (j >= usp->own->length)
93     {
94         meta_type *type_p = 0;
95         ustate_own_ty **own_data_p =
96             (ustate_own_ty **)
97             ustate_own_list_type.list_parse(usp->own, &type_p);
98         assert(type_p == &ustate_own_type);
99         own_data = (ustate_own_ty *)ustate_own_type.alloc();
100         *own_data_p = own_data;
101         own_data->project_name = project_name_get(pp).get_ref_copy();
102     }
103     assert(own_data);
104 
105     //
106     // Create a changes for the project, if necessary.
107     //
108     if (!own_data->changes)
109     {
110         own_data->changes =
111             (ustate_own_changes_list_ty *)ustate_own_changes_list_type.alloc();
112     }
113 
114     //
115     // Add another item to the changes list for the project.
116     //
117     meta_type *type_p = 0;
118     long *change_p =
119         (long int *)
120         ustate_own_changes_list_type.list_parse(own_data->changes, &type_p);
121     assert(type_p == &integer_type);
122     *change_p = change_number;
123     ustate_modified = true;
124     trace(("}\n"));
125 }
126 
127 
128 bool
own_nth(project * pp,long n,long & change_number)129 user_ty::own_nth(project *pp, long n, long &change_number)
130 {
131     trace(("user_ty::own_nth(this = %p, project_name = \"%s\", "
132         "n = %ld)\n{\n", this, project_name_get(pp).c_str(), n));
133     assert(n >= 0);
134     if (n < 0)
135     {
136         trace(("return false;\n"));
137         trace(("}\n"));
138         return false;
139     }
140     ustate_ty *usp = ustate_get(pp);
141     assert(usp->own);
142     if (!usp->own)
143     {
144         trace(("return false;\n"));
145         trace(("}\n"));
146         return false;
147     }
148 
149     //
150     // find the relevant project
151     //      and extract the n'th change
152     //
153     for (size_t j = 0; j < usp->own->length; ++j)
154     {
155         ustate_own_ty *own_data = usp->own->list[j];
156         if (project_name_get(pp) == nstring(own_data->project_name))
157         {
158             bool result = false;
159             if (own_data->changes && n < (long)own_data->changes->length)
160             {
161                 change_number = own_data->changes->list[n];
162                 result = true;
163             }
164             trace(("return %d;\n", result));
165             trace(("}\n"));
166             return result;
167         }
168     }
169 
170     trace(("return false;\n"));
171     trace(("}\n"));
172     return false;
173 }
174 
175 
176 void
own_remove(project * pp,long change_number)177 user_ty::own_remove(project *pp, long change_number)
178 {
179     trace(("user_ty::own_remove(this = %p, pp = %p, cn = %ld)\n{\n",
180         this, pp, change_number));
181     ustate_ty *usp = ustate_get(pp);
182     assert(usp->own);
183 
184     //
185     // Search for the project in the "own" list.
186     //
187     ustate_own_ty *own_data = 0;
188     size_t j = 0;
189     for (j = 0;; ++j)
190     {
191         if (j >= usp->own->length)
192         {
193             trace(("}\n"));
194             return;
195         }
196         own_data = usp->own->list[j];
197         if (nstring(own_data->project_name) == project_name_get(pp))
198             break;
199     }
200 
201     //
202     // Create the "changes" list for the project, if necessary.
203     //
204     if (!own_data->changes)
205     {
206         own_data->changes =
207             (ustate_own_changes_list_ty *)ustate_own_changes_list_type.alloc();
208     }
209 
210     //
211     // Search for the change in the "changes" list.
212     //
213     for (size_t k = 0; k < own_data->changes->length; ++k)
214     {
215         if (own_data->changes->list[k] == change_number)
216         {
217             own_data->changes->list[k] =
218                 own_data->changes->list[own_data->changes->length - 1];
219             own_data->changes->length--;
220             ustate_modified = true;
221             break;
222         }
223     }
224 
225     //
226     // If the changes list for the project is now empty,
227     // remove the project from the "own" list.
228     //
229     if (!own_data->changes->length)
230     {
231         ustate_own_type.free(own_data);
232         usp->own->list[j] =
233             usp->own->list[usp->own->length - 1];
234         usp->own->length--;
235         ustate_modified = true;
236     }
237     trace(("}\n"));
238 }
239 
240 
241 // vim: set ts=8 sw=4 et :
242