// // aegis - project change supervisor // Copyright (C) 1999, 2001-2008 Peter Miller // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see // . // #include #include #include #include #include // for assert #include #include #include #include static int src_cmp(const void *s1p, const void *s2p) { fstate_src_ty *s1; fstate_src_ty *s2; s1 = *(fstate_src_ty **)s1p; s2 = *(fstate_src_ty **)s2p; return strcmp(s1->file_name->str_text, s2->file_name->str_text); } static int long_cmp(const void *s1p, const void *s2p) { long n1; long n2; n1 = *(long *)s1p; n2 = *(long *)s2p; if (n1 < n2) return -1; if (n1 > n2) return 1; return 0; } static int string_cmp(const void *v1, const void *v2) { string_ty *s1; string_ty *s2; s1 = *(string_ty **)v1; s2 = *(string_ty **)v2; return strcmp(s1->str_text, s2->str_text); } void change_cstate_write(change::pointer cp) { string_ty *filename_new; string_ty *filename_old; static int temp_file_counter; string_ty *fn; int mode; int compress; trace(("change_cstate_write(cp = %08lX)\n{\n", (long)cp)); assert(cp->reference_count >= 1); assert(cp->pp); assert(cp->cstate_data); if (!cp->cstate_data->brief_description) cp->cstate_data->brief_description = str_from_c(""); if (!cp->cstate_data->description) cp->cstate_data->description = str_copy(cp->cstate_data->brief_description); // // force various project related files to be read in, // if they are not already // mode = 0644 & ~change_umask(cp); compress = project_compress_database_get(cp->pp); // // write out the fstate file // assert(!cp->cstate_data->src); if (cp->fstate_data) { fstate_src_list_ty *slp; // // sort the files by name // if (!cp->fstate_data->src) { cp->fstate_data->src = (fstate_src_list_ty *)fstate_src_list_type.alloc(); } slp = cp->fstate_data->src; assert(slp); assert(slp->length <= slp->maximum); assert(!slp->list == !slp->maximum); if (slp->length >= 2) { qsort(slp->list, slp->length, sizeof(*slp->list), src_cmp); } fn = change_fstate_filename_get(cp); filename_new = str_format("%s,%d", fn->str_text, ++temp_file_counter); filename_old = str_format("%s,%d", fn->str_text, ++temp_file_counter); change_become(cp); if (cp->fstate_is_a_new_file) { string_ty *s1; string_ty *s2; s1 = project_Home_path_get(cp->pp); s2 = os_below_dir(s1, fn); os_mkdir_between(s1, s2, 02755); str_free(s2); undo_unlink_errok(filename_new); fstate_write_file(filename_new, cp->fstate_data, compress); commit_rename(filename_new, fn); cp->fstate_is_a_new_file = 0; } else { undo_unlink_errok(filename_new); fstate_write_file(filename_new, cp->fstate_data, compress); commit_rename(fn, filename_old); commit_rename(filename_new, fn); commit_unlink_errok(filename_old); } // // Change the file mode as appropriate. // (Only need to do this for new files, but be paranoid.) // os_chmod(filename_new, mode); change_become_undo(cp); str_free(filename_new); str_free(filename_old); } // // force the change list to be sorted // assert(cp->cstate_data); if (cp->cstate_data->branch && cp->cstate_data->branch->change) { cstate_branch_change_list_ty *lp; lp = cp->cstate_data->branch->change; qsort(lp->list, lp->length, sizeof(lp->list[0]), long_cmp); } // // Force the staff lists to be sorted. // (It helps makes the tests pass, if nothing else.) // if (cp->cstate_data->branch && cp->cstate_data->branch->administrator) { cstate_branch_administrator_list_ty *lp; lp = cp->cstate_data->branch->administrator; qsort(lp->list, lp->length, sizeof(lp->list[0]), string_cmp); } if (cp->cstate_data->branch && cp->cstate_data->branch->developer) { cstate_branch_developer_list_ty *lp; lp = cp->cstate_data->branch->developer; qsort(lp->list, lp->length, sizeof(lp->list[0]), string_cmp); } if (cp->cstate_data->branch && cp->cstate_data->branch->reviewer) { cstate_branch_reviewer_list_ty *lp; lp = cp->cstate_data->branch->reviewer; qsort(lp->list, lp->length, sizeof(lp->list[0]), string_cmp); } if (cp->cstate_data->branch && cp->cstate_data->branch->integrator) { cstate_branch_integrator_list_ty *lp; lp = cp->cstate_data->branch->integrator; qsort(lp->list, lp->length, sizeof(lp->list[0]), string_cmp); } // // write out the cstate file // fn = change_cstate_filename_get(cp); assert(!cp->cstate_data->src); filename_new = str_format("%s,%d", fn->str_text, ++temp_file_counter); filename_old = str_format("%s,%d", fn->str_text, ++temp_file_counter); change_become(cp); if (cp->cstate_is_a_new_file) { string_ty *s1; string_ty *s2; s1 = project_Home_path_get(cp->pp); s2 = os_below_dir(s1, fn); os_mkdir_between(s1, s2, 02755); str_free(s2); undo_unlink_errok(filename_new); cstate_write_file(filename_new, cp->cstate_data, compress); commit_rename(filename_new, fn); cp->cstate_is_a_new_file = 0; } else { undo_unlink_errok(filename_new); cstate_write_file(filename_new, cp->cstate_data, compress); commit_rename(fn, filename_old); commit_rename(filename_new, fn); commit_unlink_errok(filename_old); } // // Change the file mode as appropriate. // (Only need to do this for new files, but be paranoid.) // os_chmod(filename_new, mode); change_become_undo(cp); str_free(filename_new); str_free(filename_old); trace(("}\n")); }