clean up empty directories after migration and prompt user about remaining files

This commit is contained in:
myk
2013-03-12 08:59:54 +00:00
parent ef5ee3329e
commit 460401e027
3 changed files with 107 additions and 16 deletions

View File

@@ -65,7 +65,7 @@ public class DialogMigrateProfile {
private volatile boolean _cancel;
public DialogMigrateProfile(String srcDir, boolean showMigrationBlurb, final Runnable onImportSuccessful) {
public DialogMigrateProfile(String srcDir, boolean showMigrationBlurb, final Runnable onDialogClose) {
FPanel p = new FPanel(new MigLayout("insets dialog, gap 0, center, wrap"));
p.setOpaque(false);
p.setBackgroundTexture(FSkin.getIcon(FSkin.Backgrounds.BG_TEXTURE));
@@ -131,14 +131,17 @@ public class DialogMigrateProfile {
final FButton btnCancel = new FButton("Cancel");
btnCancel.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) { _cancel = true; cleanup.run(); }
@Override public void actionPerformed(ActionEvent e) {
_cancel = true;
cleanup.run();
if (null != onDialogClose) {
onDialogClose.run();
}
}
});
_onImportSuccessful = new Runnable() {
@Override public void run() {
if (null != onImportSuccessful) {
onImportSuccessful.run();
}
btnCancel.setText("Done");
}
};
@@ -492,6 +495,8 @@ public class DialogMigrateProfile {
// assumes all destination directories have been created
int numOps = 0;
int numSucceeded = 0;
int numFailed = 0;
for (Map.Entry<File, File> op : _operations.entrySet()) {
if (_cancel) { break; }
@@ -519,13 +524,18 @@ public class DialogMigrateProfile {
_operationLog.append(String.format("%s %s -> %s\n",
_move ? "Moved" : "Copied",
srcFile.getAbsolutePath(), destFile.getAbsolutePath()));
++numSucceeded;
} catch (IOException e) {
_operationLog.append(String.format("Failed to %s %s -> %s (%s)\n",
_move ? "move" : "copy",
srcFile.getAbsolutePath(), destFile.getAbsolutePath(),
e.getMessage()));
++numFailed;
}
}
_operationLog.append(String.format("\nImport complete. %d files %s, %d errors",
numSucceeded, _move ? "moved" : "copied", numFailed));
} catch (final Exception e) {
_cancel = true;

View File

@@ -78,7 +78,7 @@ public final class NewConstants {
public static final FileLocation HOME_LAYOUT_FILE = new FileLocation(_DEFAULTS_DIR, USER_PREFS_DIR, "home.xml");
public static final FileLocation MATCH_LAYOUT_FILE = new FileLocation(_DEFAULTS_DIR, USER_PREFS_DIR, "match.xml");
public static final FileLocation EDITOR_LAYOUT_FILE = new FileLocation(_DEFAULTS_DIR, USER_PREFS_DIR, "editor.xml");
public static final FileLocation GAUNTLET_DIR = new FileLocation(_DEFAULTS_DIR, USER_DIR, "gauntlet/");
public static final FileLocation GAUNTLET_DIR = new FileLocation(_DEFAULTS_DIR, USER_DIR, "gauntlet/");
// data that is only in the cached dir
private static final String _PICS_DIR = CACHE_DIR + "pics/";
@@ -97,6 +97,7 @@ public final class NewConstants {
CACHE_DIR,
CACHE_CARD_PICS_DIR,
USER_PREFS_DIR,
GAUNTLET_DIR.userPrefLoc,
DB_DIR,
DECK_CONSTRUCTED_DIR,
DECK_DRAFT_DIR,

View File

@@ -3,28 +3,39 @@ package forge.view;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import net.miginfocom.swing.MigLayout;
import org.apache.commons.lang3.StringUtils;
import com.google.common.collect.Lists;
import forge.Singletons;
import forge.control.FControl;
import forge.gui.DialogMigrateProfile;
import forge.gui.SOverlayUtils;
import forge.gui.deckeditor.VDeckEditorUI;
import forge.gui.framework.DragCell;
import forge.gui.framework.EDocID;
@@ -32,6 +43,8 @@ import forge.gui.framework.SLayoutConstants;
import forge.gui.home.VHomeUI;
import forge.gui.match.TargetingOverlay;
import forge.gui.match.VMatchUI;
import forge.gui.toolbox.FButton;
import forge.gui.toolbox.FLabel;
import forge.gui.toolbox.FOverlay;
import forge.gui.toolbox.FPanel;
import forge.gui.toolbox.FSkin;
@@ -128,30 +141,97 @@ public enum FView {
{
// get profile directories -- if one of them is actually under the res directory, don't
// try to migrate it
Set<File> profileDirs = new HashSet<File>();
final Set<File> profileDirs = new HashSet<File>();
for (String dname : NewConstants.PROFILE_DIRS) {
profileDirs.add(new File(dname));
}
final List<File> resDirs = new ArrayList<File>();
for (String resDir : Lists.newArrayList("decks", "gauntlet", "layouts", "pics", "pics_product", "preferences", "quest/data")) {
resDirs.add(new File("res", resDir));
}
// check quickly whether we have any data to migrate
boolean hasData = false;
for (String resDir : Lists.newArrayList("decks", "gauntlet", "layouts", "pics", "pics_product", "preferences", "quest/data")) {
File f = new File("res", resDir);
if (f.exists() && !profileDirs.contains(f)) {
System.out.println("profile data found in obsolete location: " + f.getAbsolutePath());
for (File resDir : resDirs) {
if (resDir.exists() && !profileDirs.contains(resDir)) {
// cycle through all dirs instead of breaking after the first found so each dir is printed to stdout
System.out.println("profile data found in obsolete location: " + resDir.getAbsolutePath());
hasData = true;
// cycle through all dirs instead of breaking immediately so each dir is printed to stdout
}
}
if (hasData) {
new DialogMigrateProfile("res", true, new Runnable() {
@Override public void run() {
// TODO: reload appropriate data structures
// attempt to remove old directories and assemble a list of remaining files.
Deque<File> stack = new LinkedList<File>(resDirs);
Set<File> seenDirs = new HashSet<File>();
List<File> remainingFiles = new LinkedList<File>();
while (!stack.isEmpty()) {
File cur = stack.peek();
if (profileDirs.contains(cur)) {
// don't touch active profile dirs
stack.pop();
continue;
}
if (seenDirs.contains(cur)) {
boolean succeeded = stack.pop().delete();
System.out.println(String.format("attempting to remove old profile dir: %s (%s)",
cur, succeeded ? "succeeded" : "failed"));
continue;
}
seenDirs.add(cur);
File[] curListing = cur.listFiles();
if (null == curListing) {
continue;
}
for (File f : curListing) {
if (f.isDirectory()) {
stack.push(f);
} else {
remainingFiles.add(f);
}
}
}
// TODO: attempt to remove old directories. if they are not empty, show a dialog
// TODO: telling them that there is some data remaining and it should be moved or deleted manually
// TODO: they will continue to be prompted for migration until the directories are gone
// if any files remain, show a dialog saying so and that they should be moved or
// deleted manually or the user will continue to be prompted for migration
FPanel p = new FPanel(new MigLayout("insets dialog, gap 10, center, wrap"));
p.setOpaque(false);
p.setBackgroundTexture(FSkin.getIcon(FSkin.Backgrounds.BG_TEXTURE));
p.add(new FLabel.Builder().text("<html>There seem to be a few files left over in your old data" +
" directories. They should be deleted or moved somewhere else to avoid having this data" +
" migration message pop up again!</html>").build());
JTextArea files = new JTextArea(StringUtils.join(remainingFiles, '\n'));
files.setFont(new Font("Monospaced", Font.PLAIN, 10));
files.setOpaque(false);
files.setWrapStyleWord(true);
files.setLineWrap(true);
files.setEditable(false);
JScrollPane scroller = new JScrollPane(files);
p.add(scroller, "w 600:100%:100%, h 60:100%:100%");
final FButton btnOk = new FButton("OK");
btnOk.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) { SOverlayUtils.hideOverlay(); }
});
p.add(btnOk, "center, w 40%, h pref+12!");
JPanel overlay = FOverlay.SINGLETON_INSTANCE.getPanel();
overlay.setLayout(new MigLayout("insets 0, gap 0, wrap, ax center, ay center"));
overlay.add(p, "w 800::80%, h 500::90%");
SOverlayUtils.showOverlay();
SwingUtilities.invokeLater(new Runnable() {
@Override public void run() { btnOk.requestFocusInWindow(); }
});
// TODO: reload appropriate data structures
}
});
}