void RemoteRepositoryAssistant::entry_changed_timeout()
{
  // Progress.
  ProgressWindow progresswindow (_("Testing read access"), false);
  progresswindow.set_fraction (0.5);
  
  // Event done.
  event_id_entry_repository = 0;

  // Test read access to the repository.
  GwSpawn spawn("git");
  spawn.arg("ls-remote");
  spawn.arg(repository_url_get());
  spawn.read();
  spawn.run();
  bool access = spawn.exitstatus == 0;
  ustring message;
  if (access) {
    message = _("Read access to the repository has been granted");
  } else {
    message = _("Cannot access the repository:");
    for (unsigned int i = 0; i < spawn.standarderr.size(); i++) {
      message.append("\n");
      message.append(spawn.standarderr[i]);
    }
  }
  gtk_label_set_text (GTK_LABEL (label_repository_accessible), message.c_str());
  gtk_assistant_set_page_complete (GTK_ASSISTANT (assistant), vbox_repository, access);
}
Esempio n. 2
0
void git_upgrade ()
// Upgrades the git system.
{
  // Go through the projects that have their git repository enabled.
  extern Settings * settings;
  vector <ustring> projects = projects_get_all ();
  for (unsigned int i = 0; i < projects.size(); i++) {
    ProjectConfiguration * projectconfig = settings->projectconfig (projects[i]);
    ustring git_directory = gw_build_filename (project_data_directory_project (projects[i]), ".git");
    if (projectconfig->git_use_remote_repository_get()) {
      // At times there's a stale index.lock file that prevents any collaboration.
      // This is to be removed.
      ustring index_lock = gw_build_filename (git_directory, "index.lock");
      if (g_file_test (index_lock.c_str(), G_FILE_TEST_IS_REGULAR)) {
        gw_message (_("Cleaning out index lock ") + index_lock);
        unix_unlink (index_lock.c_str());
      }
      // Get the data directory for the project
      ustring datadirectory = tiny_project_data_directory_project(projects[i]);
      // On most machines git can determine the user's name from the system services. 
      // On the XO machine, it can't. It is set here manually. 
      // On more recent versions of git, like version 1.8.3 and younger,
      // although git may determine the user's name from the system, 
      // it still requires it to be set manually.
      ustring command;
      command = "git config user.email \"";
      command.append(g_get_user_name());
      command.append("@");
      command.append(g_get_host_name());
      command.append("\"");
      maintenance_register_shell_command (datadirectory, command);
      command = "git config user.name \"";
      command.append(g_get_real_name());
      command.append("\"");
      maintenance_register_shell_command (datadirectory, command);
      // (Re)initialize the repository. This can be done repeatedly without harm.
      // Note that this is done on shutdown.
      maintenance_register_shell_command (datadirectory, "git init");
    } else {
      if (g_file_test (git_directory.c_str(), G_FILE_TEST_IS_DIR)) {
        gw_message (_("Cleaning out folder ") + git_directory);
        ProgressWindow progresswindow (_("Tidying up project ") + projects[i], false);
        progresswindow.set_fraction (0.5);
        unix_rmdir (git_directory);
      }
    }
  }
}
void RemoteRepositoryAssistant::on_button_clone ()
{
  // Progress.
  ProgressWindow progresswindow (_("Cloning repository"), false);
  progresswindow.set_fraction (0.5);
  
  // Clear out persistent clone directory.
  repository_unclone();
  
  // Create temporal clone directory.
  ustring temporal_clone_directory = git_testing_directory ("tempclone");
  unix_rmdir(temporal_clone_directory);
  gw_mkdir_with_parents(temporal_clone_directory);
  
  // Clone the remote repository
  GwSpawn spawn("git");
  spawn.workingdirectory(temporal_clone_directory);
  spawn.arg ("clone");
  spawn.arg(repository_url_get());
  spawn.run();

  if (spawn.exitstatus == 0) {
    // Move the cloned repository into the persistent clone directory.
    ReadDirectories rd (temporal_clone_directory, "", "");
    if (!rd.directories.empty()) {
      ustring subdirectory = rd.directories[0];
      subdirectory = gw_build_filename (temporal_clone_directory, subdirectory);
      unix_mv (subdirectory, persistent_clone_directory);
    }
    unix_rmdir(temporal_clone_directory);
  } else {
    // Clone failed, clear out any remains.
    repository_unclone();
  }  
  
  // Update structures.
  gtk_assistant_set_page_complete (GTK_ASSISTANT (assistant), vbox_clone, repository_was_cloned());
  if (repository_was_cloned()) {
    gtk_label_set_text (GTK_LABEL (label_clone), _("The data has been cloned, you can go forward"));
    previously_cloned_url = repository_url_get();
  } else {
    gtk_label_set_text (GTK_LABEL (label_clone), _("Cloning the data failed, please try again"));
    repository_unclone();
  }
}
void RemoteRepositoryAssistant::on_button_push ()
/*
It copies the existing data, without the .git directory, into the persistent clone,
replaces any data that was there, and then pushes this data to the remote repository.
This makes the remote repository to have an exact copy of our data.
*/
{
  // Progress.
  ProgressWindow progresswindow (_("Pushing your data"), false);
  progresswindow.set_fraction (0.2);
  
  // Copy our data into a temporal location.
  ustring my_data_directory = notes_shared_storage_folder ();
  if (bible_notes_selector_bible ())
    my_data_directory = project_data_directory_project(bible);
  ustring temporal_data_directory = git_testing_directory ("mydata");
  unix_cp_r (my_data_directory, temporal_data_directory);

  // In rare cases a .git directory could have been copied along with our data. Remove that.
  unix_rmdir (gw_build_filename (temporal_data_directory, ".git"));

  // Remove all directories and all files from the persistent clone directory, but leave the .git directory
  {
    ReadDirectories rd (persistent_clone_directory, "", "");
    for (unsigned int i = 0; i < rd.directories.size(); i++) {
      if (rd.directories[i] != ".git") {
        unix_rmdir (gw_build_filename (persistent_clone_directory, rd.directories[i]));
      }
    }
    ReadFiles rf (persistent_clone_directory, "", "");
    for (unsigned int i = 0; i < rf.files.size(); i++) {
      unlink (gw_build_filename (persistent_clone_directory, rf.files[i]).c_str());
    }
  }
  
  // Move our data, from its temporal location, into the persistent clone directory.
  progresswindow.set_fraction (0.4);
  {
    ReadDirectories rd (temporal_data_directory, "", "");
    for (unsigned int i = 0; i < rd.directories.size(); i++) {
      unix_mv (gw_build_filename (temporal_data_directory, rd.directories[i]), persistent_clone_directory);
    }
    ReadFiles rf (temporal_data_directory, "", "");
    for (unsigned int i = 0; i < rf.files.size(); i++) {
      unix_mv (gw_build_filename (temporal_data_directory, rf.files[i]), persistent_clone_directory);
    }
  }

  // Commit the new data in the persistent clone directory.
  progresswindow.set_fraction (0.55);
  {
    GwSpawn spawn ("git");
    spawn.workingdirectory (persistent_clone_directory);
    spawn.arg ("add");
    spawn.arg (".");
    spawn.run ();
  }
  progresswindow.set_fraction (0.65);
  {
    GwSpawn spawn ("git");
    spawn.workingdirectory (persistent_clone_directory);
    spawn.arg ("commit");
    spawn.arg ("-a");
    spawn.arg ("-m");
    spawn.arg ("user data into repo");
    spawn.run ();
  }

  // Push our data to the remote repository.
  progresswindow.set_fraction (0.8);
  GwSpawn spawn("git");
  spawn.workingdirectory(persistent_clone_directory);
  spawn.arg ("push");
  spawn.run();

  // Take action depending on the outcome of pushing to the remote repository.
  if (spawn.exitstatus == 0) {
    // Clone okay.
    gtk_label_set_text (GTK_LABEL (label_push), _("Your data has been pushed to the remote repository"));
  } else {
    // Clone failed.
    gtk_label_set_text (GTK_LABEL (label_push), _("Your data could not be pushed to the remote repository,\nplease restart the assistant"));
    repository_unclone();
  }  
}
void RemoteRepositoryAssistant::test_write_access ()
// Checks whether there is write access from the local clone to the remote repository.
{
  // GUI update.
  // If a wrong host is entered as the git repository, the testing for the write access
  // may "hang" for a long time. For that reason it can be cancelled by the user.
  ProgressWindow progresswindow (_("Testing write access"), true);
  gtk_label_set_text (GTK_LABEL (label_write_test), _("Testing write access to the remote repository"));

  // Temporal file for trying write access.
  ustring filename = "test_repository_writable";
  g_file_set_contents(gw_build_filename(persistent_clone_directory, filename).c_str(), "", 0, NULL);

  // Add this file and commit it locally.
  progresswindow.set_fraction (0.2);
  {
    GwSpawn spawn("git");
    spawn.workingdirectory(persistent_clone_directory);
    spawn.arg("add");
    spawn.arg(".");
    spawn.run();
    write_access_granted = (spawn.exitstatus == 0);
  }
  if (write_access_granted) {
    GwSpawn spawn("git");
    spawn.workingdirectory(persistent_clone_directory);
    spawn.arg("commit");
    spawn.arg("-m");
    spawn.arg("Write test");
    spawn.arg("-a");
    spawn.run();
    write_access_granted = (spawn.exitstatus == 0);
  }

  // Pull changes.
  progresswindow.set_fraction (0.4);
  if (write_access_granted) {
    GwSpawn spawn("git");
    spawn.workingdirectory(persistent_clone_directory);
    spawn.arg ("pull");
    spawn.run();
    // When pulling from an empty repository, the exit status is undefined.
    // So we cannot test for it here.
    // write_access_granted = (spawn.exitstatus == 0);
  }
  // Push the changes to see if there is write access. 
  // Notice the --all switch to be used when pushing to an empty remote repository.
  progresswindow.set_fraction (0.6);
  if (write_access_granted) {
    GwSpawn spawn("git");
    spawn.workingdirectory(persistent_clone_directory);
    spawn.arg ("push");
    spawn.arg ("--all");
    spawn.run();
    write_access_granted = (spawn.exitstatus == 0);
  }

  // Remove the temporal file again from the remote repository.
  progresswindow.set_fraction (0.8);
  unlink(gw_build_filename(persistent_clone_directory, filename).c_str());
  if (write_access_granted) {
    GwSpawn spawn("git");
    spawn.workingdirectory(persistent_clone_directory);
    spawn.arg("commit");
    spawn.arg("-m");
    spawn.arg("Write test");
    spawn.arg("-a");
    spawn.run();
    write_access_granted = (spawn.exitstatus == 0);
  }
  progresswindow.set_fraction (1);
  if (write_access_granted) {
    GwSpawn spawn("git");
    spawn.workingdirectory(persistent_clone_directory);
    spawn.arg ("push");
    spawn.run();
    write_access_granted = (spawn.exitstatus == 0);
  }

  // Set the GUI.
  gtk_assistant_set_page_complete (GTK_ASSISTANT (assistant), label_write_test, write_access_granted);
  if (write_access_granted) {
    gtk_label_set_text (GTK_LABEL (label_write_test), _("Write access was granted, you can go forward"));
  } else {
    gtk_label_set_text (GTK_LABEL (label_write_test), _("No write access. Please check the system log for more information"));
  }  
}
bool RemoteRepositoryAssistant::try_git ()
// Tries git and returns true if everything's fine.
{
  // Progress.
  ProgressWindow progresswindow (_("Trying the contents tracker"), false);
  
  // Whether git is okay.
  bool okay = true;
  
  if (okay) {
    progresswindow.set_fraction (0.05);
    gw_message (_("Check git version number"));
    okay = check_git_version ();
  }
  
  // Clean the directory to work in.
  {
    ustring directory = git_testing_directory ("");
    unix_rmdir (directory);
    gw_mkdir_with_parents (directory);
  }
  
  if (okay) {
    progresswindow.set_fraction (0.11);
    gw_message (_("Create first local repository"));
    okay = try_git_create_repository ("local1", false);
  }

  if (okay) {
    progresswindow.set_fraction (0.17);
    gw_message (_("Store data into first local repository"));
    okay = try_git_store_data_in_repository ("local1", "--test--");
  }

  if (okay) {
    progresswindow.set_fraction (0.23);
    gw_message (_("Create remote repository"));
    okay = try_git_create_repository ("remote", true);
  }

  if (okay) {
    progresswindow.set_fraction (0.29);
    gw_message (_("Fetch data from the first local repository into the remote one"));
    okay = try_git_fetch_repository ("remote", "local1");
  }

  if (okay) {
    progresswindow.set_fraction (0.35);
    gw_message (_("Checkout the first local repository"));
    okay = try_git_checkout_repository ("local1", "remote");
  }

  if (okay) {
    progresswindow.set_fraction (0.41);
    gw_message (_("Check data of first local repository"));
    okay = try_git_check_data_in_repository ("local1", "--test--");
  }

  if (okay) {
    progresswindow.set_fraction (0.47);
    gw_message (_("Checkout the second local repository"));
    okay = try_git_checkout_repository ("local2", "remote");
  }

  if (okay) {
    progresswindow.set_fraction (0.52);
    gw_message (_("Check data of second local repository"));
    okay = try_git_check_data_in_repository ("local2", "--test--");
  }

  if (okay) {
    progresswindow.set_fraction (0.58);
    gw_message (_("Store different data into first repository"));
    okay = try_git_store_data_in_repository ("local1", "---test---");
  }

  if (okay) {
    progresswindow.set_fraction (0.64);
    gw_message (_("Push first repository"));
    okay = try_git_push_repository ("local1");
  }

  if (okay) {
    progresswindow.set_fraction (0.70);
    gw_message (_("Pull second repository"));
    okay = try_git_pull_repository ("local2");
  }

  if (okay) {
    progresswindow.set_fraction (0.76);
    gw_message ("Check data in second repository");
    okay = try_git_check_data_in_repository ("local2", "---test---");
  }

  if (okay) {
    progresswindow.set_fraction (0.82);
    gw_message (_("Store different data into second repository"));
    okay = try_git_store_data_in_repository ("local2", "----test----");
  }

  if (okay) {
    progresswindow.set_fraction (0.88);
    gw_message (_("Push second repository"));
    okay = try_git_push_repository ("local2");
  }

  if (okay) {
    progresswindow.set_fraction (0.94);
    gw_message (_("Pull first repository"));
    okay = try_git_pull_repository ("local1");
  }

  if (okay) {
    progresswindow.set_fraction (1);
    gw_message (_("Check data in first repository"));
    okay = try_git_check_data_in_repository ("local1", "----test----");
  }

  // Return whether git is ok.
  return okay;
}