1 //
2 //      aegis - project change supervisor
3 //      Copyright (C) 2002-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/error.h>
23 #include <common/trace.h>
24 #include <libaegis/change/file.h>
25 #include <libaegis/change.h>
26 #include <libaegis/fstate.fmtgen.h>
27 #include <libaegis/os.h>
28 #include <libaegis/project/file.h>
29 #include <libaegis/project.h>
30 #include <libaegis/undo.h>
31 #include <libaegis/user.h>
32 
33 
34 string_ty *
project_file_version_path(project * pp,fstate_src_ty * src,int * unlink_p)35 project_file_version_path(project *pp, fstate_src_ty *src, int *unlink_p)
36 {
37     project      *ppp;
38     change::pointer cp;
39     string_ty       *filename;
40     history_version_ty *ed;
41     fstate_src_ty   *reconstruct;
42 
43     trace(("project_file_version_path(pp = %p, src = %p, "
44         "unlink_p = %p)\n{\n", pp, src, unlink_p));
45     assert(src);
46     assert(src->file_name);
47     trace(("fn \"%s\"\n", src->file_name->str_text));
48     assert(src->edit || src->edit_origin);
49     ed = src->edit ? src->edit : src->edit_origin;
50     assert(ed->revision);
51     trace(("rev \"%s\"\n", ed->revision->str_text));
52     if (unlink_p)
53         *unlink_p = 0;
54     for (ppp = pp; ppp; ppp = (ppp->is_a_trunk() ? 0 : ppp->parent_get()))
55     {
56         cp = ppp->change_get();
57         if (cp->is_completed())
58             continue;
59         fstate_src_ty *old_src =
60             cp->file_find(nstring(src->file_name), view_path_first);
61         if (!old_src)
62             continue;
63         switch (old_src->action)
64         {
65         case file_action_remove:
66         case file_action_transparent:
67             continue;
68 
69         case file_action_create:
70         case file_action_modify:
71         case file_action_insulate:
72 #ifndef DEBUG
73         default:
74 #endif
75             // should be file_action_remove
76             assert(!old_src->deleted_by);
77             if (old_src->deleted_by)
78                 continue;
79 
80             // should be file_action_transparent
81             assert(!old_src->about_to_be_created_by);
82             if (old_src->about_to_be_created_by)
83                 continue;
84 
85             // should be file_action_transparent
86             assert(!old_src->about_to_be_copied_by);
87             if (old_src->about_to_be_copied_by)
88                 continue;
89             break;
90         }
91         assert(old_src->edit);
92         assert(old_src->edit->revision);
93         if (str_equal(old_src->edit->revision, ed->revision))
94         {
95             filename = cp->file_path(src->file_name);
96             //
97             // The following check is needed to make aegis work even
98             // when filename does'not exists.
99             //
100             os_become_orig();
101             int file_exists = os_exists(filename);
102             os_become_undo();
103             assert(file_exists);
104             if (!file_exists)
105                 break;
106             trace(("return \"%s\";\n", filename->str_text));
107             trace(("}\n"));
108             return filename;
109         }
110     }
111 
112     filename = os_edit_filename(0);
113     os_become_orig();
114     undo_unlink_errok(filename);
115     os_become_undo();
116     if (unlink_p)
117         *unlink_p = 1;
118 
119     reconstruct = (fstate_src_ty *)fstate_src_type.alloc();
120     reconstruct->file_name = str_copy(src->file_name);
121     reconstruct->edit = history_version_copy(ed);
122     change_file_copy_basic_attributes(reconstruct, src);
123 
124     cp = pp->change_get();
125     change_run_history_get_command
126     (
127         cp,
128         reconstruct,
129         filename,
130         user_ty::create()
131     );
132     fstate_src_type.free(reconstruct);
133     trace(("return \"%s\";\n", filename->str_text));
134     trace(("}\n"));
135     return filename;
136 }
137 
138 
139 // vim: set ts=8 sw=4 et :
140