<commit_before>package org.basex.core.cmd;

import static org.basex.core.Text.*;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import org.basex.core.Command;
import org.basex.core.Context;
import org.basex.core.Prop;
import org.basex.core.User;
import org.basex.io.IO;
import org.basex.util.StringList;
import org.basex.util.Util;

/**
 * Evaluates the 'restore' command and restores a backup of a database.
 *
 * @author BaseX Team 2005-11, ISC License
 * @author <NAME>
 */
public final class Restore extends Command {
  /** Counter for outstanding files. */
  private int of;
  /** Counter of total files. */
  private int tf;

  /**
   * Default constructor.
   * @param arg optional argument
   */
  public Restore(final String arg) {
    super(User.CREATE, arg);
  }

  @Override
  protected boolean run() {
    String db = args[0];
    if(!validName(db)) return error(NAMEINVALID, db);
    
    String tmp = prop.get(Prop.DBPATH) + Prop.SEP + db + IO.ZIPSUFFIX;
    File file = new File(tmp);
    if(!file.exists()) {
      final StringList list = list(db + '-', context);
      if(list.size() == 0) return error(DBBACKNF, db);
      file = new File(list.get(0));
    }
    if(!file.exists()) return error(DBBACKNF, db);

    // close database if it's currently opened and not opened by others
    final boolean closed = close(db);

    // check if database is pinned
    if(context.pinned(db)) return error(DBLOCKED, db);

    // try to restore database
    return restore(file, prop) && (!closed || new Open(db).run(context)) ?
        info(DBRESTORE, file.getName(), perf) : error(DBNORESTORE, db);
  }

  /**
   * Restores the specified database.
   * @param file file
   * @param pr database properties
   * @return success flag
   */
  private boolean restore(final File file, final Prop pr) {
    try {
      // count number of files
      InputStream is = new BufferedInputStream(new FileInputStream(file));
      ZipInputStream zis = new ZipInputStream(is);
      while(zis.getNextEntry() != null) tf++;
      zis.close();
      // reopen zip stream
      is = new BufferedInputStream(new FileInputStream(file));
      zis = new ZipInputStream(is);

      final byte[] data = new byte[IO.BLOCKSIZE];
      ZipEntry e;
      while((e = zis.getNextEntry()) != null) {
        of++;
        final String path = pr.get(Prop.DBPATH) + Prop.SEP + e.getName();
        if(e.isDirectory()) {
          new File(path).mkdir();
        } else {
          final BufferedOutputStream bos = new BufferedOutputStream(
              new FileOutputStream(path));
          int c;
          while((c = zis.read(data)) != -1) bos.write(data, 0, c);
          bos.close();
        }
      }
      zis.close();
      return true;
    } catch(final IOException ex) {
      Util.debug(ex);
      return false;
    }
  }

  /**
   * Returns all backups of the specified database.
   * @param db database
   * @param ctx database context
   * @return available backups
   */
  public static StringList list(final String db, final Context ctx) {
    // create database list
    final StringList list = new StringList();

    final IO dir = IO.get(ctx.prop.get(Prop.DBPATH));
    if(!dir.exists()) return list;

    final String pre = db + (db.contains("-") ? "" : "-");
    for(final IO f : dir.children()) {
      final String n = f.name();
      if(n.startsWith(pre) && n.endsWith(IO.ZIPSUFFIX)) list.add(f.path());
    }
    list.sort(false, false);
    return list;
  }


  @Override
  protected String tit() {
    return BUTTONRESTORE;
  }

  @Override
  public boolean supportsProg() {
    return true;
  }

  @Override
  protected double prog() {
    return (double) of / tf;
  }
}<commit_msg>[FIX] restore command fixed<commit_after>package org.basex.core.cmd;

import static org.basex.core.Text.*;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import org.basex.core.Command;
import org.basex.core.Context;
import org.basex.core.Prop;
import org.basex.core.User;
import org.basex.io.IO;
import org.basex.util.StringList;
import org.basex.util.Util;

/**
 * Evaluates the 'restore' command and restores a backup of a database.
 *
 * @author BaseX Team 2005-11, ISC License
 * @author <NAME>
 */
public final class Restore extends Command {
  /** Counter for outstanding files. */
  private int of;
  /** Counter of total files. */
  private int tf;

  /**
   * Default constructor.
   * @param arg optional argument
   */
  public Restore(final String arg) {
    super(User.CREATE, arg);
  }

  @Override
  protected boolean run() {
    String db = args[0];
    if(!validName(db)) return error(NAMEINVALID, db);
    
    String tmp = prop.get(Prop.DBPATH) + Prop.SEP + db + IO.ZIPSUFFIX;
    File file = new File(tmp);
    if(!file.exists()) {
      final StringList list = list(db, context);
      if(list.size() == 0) return error(DBBACKNF, db);
      file = new File(list.get(0));
      if(!file.exists()) return error(DBBACKNF, db);
    } else {
      db = db.substring(0, db.length() - 20);
    }

    // close database if it's currently opened and not opened by others
    final boolean closed = close(db);

    // check if database is pinned
    if(context.pinned(db)) return error(DBLOCKED, db);

    // try to restore database
    return restore(file, prop) && (!closed || new Open(db).run(context)) ?
        info(DBRESTORE, file.getName(), perf) : error(DBNORESTORE, db);
  }

  /**
   * Restores the specified database.
   * @param file file
   * @param pr database properties
   * @return success flag
   */
  private boolean restore(final File file, final Prop pr) {
    try {
      // count number of files
      InputStream is = new BufferedInputStream(new FileInputStream(file));
      ZipInputStream zis = new ZipInputStream(is);
      while(zis.getNextEntry() != null) tf++;
      zis.close();
      // reopen zip stream
      is = new BufferedInputStream(new FileInputStream(file));
      zis = new ZipInputStream(is);

      final byte[] data = new byte[IO.BLOCKSIZE];
      ZipEntry e;
      while((e = zis.getNextEntry()) != null) {
        of++;
        final String path = pr.get(Prop.DBPATH) + Prop.SEP + e.getName();
        if(e.isDirectory()) {
          new File(path).mkdir();
        } else {
          final BufferedOutputStream bos = new BufferedOutputStream(
              new FileOutputStream(path));
          int c;
          while((c = zis.read(data)) != -1) bos.write(data, 0, c);
          bos.close();
        }
      }
      zis.close();
      return true;
    } catch(final IOException ex) {
      Util.debug(ex);
      return false;
    }
  }

  /**
   * Returns all backups of the specified database.
   * @param db database
   * @param ctx database context
   * @return available backups
   */
  public static StringList list(final String db, final Context ctx) {
    // create database list
    final StringList list = new StringList();

    final IO dir = IO.get(ctx.prop.get(Prop.DBPATH));
    if(!dir.exists()) return list;
    final String pre = db + "-";
    Pattern p = Pattern.compile(pre + "\\d{4}.*");
    
    for(final IO f : dir.children()) {
      final String n = f.name();
      Matcher m = p.matcher(n);
      if(n.startsWith(pre) && m.matches() && 
          n.endsWith(IO.ZIPSUFFIX)) list.add(f.path());
    }
    list.sort(false, false);
    return list;
  }


  @Override
  protected String tit() {
    return BUTTONRESTORE;
  }

  @Override
  public boolean supportsProg() {
    return true;
  }

  @Override
  protected double prog() {
    return (double) of / tf;
  }
}
{'fraction_non_alphanumeric': 0.13125309559187717, 'fraction_numerical': 0.0032194155522535907, 'mean_word_length': 2.7532527881040894, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '125114', 'n_tokens_mistral': 2566, 'n_tokens_neox': 2492, 'n_words': 705}