From ad3e1ed33a44064139b6a0f0a777566f40d98283 Mon Sep 17 00:00:00 2001
From: Nikos Skalkotos <skalkoto@grnet.gr>
Date: Wed, 21 May 2014 17:57:44 +0300
Subject: [PATCH] Rewrite file selection function

Make it more general. Till know it was only used for selecting the input
media but other parts of the program should also make use of it.
---
 image_creator/dialog_main.py | 48 +++++++------------------
 image_creator/dialog_util.py | 69 ++++++++++++++++++++++++++++++++++++
 2 files changed, 81 insertions(+), 36 deletions(-)

diff --git a/image_creator/dialog_main.py b/image_creator/dialog_main.py
index fe9ca1d..88c295a 100644
--- a/image_creator/dialog_main.py
+++ b/image_creator/dialog_main.py
@@ -24,7 +24,6 @@ user is asked if he wants to use the program in expert or wizard mode.
 import dialog
 import sys
 import os
-import stat
 import textwrap
 import signal
 import optparse
@@ -41,8 +40,8 @@ from image_creator.output.composite import CompositeOutput
 from image_creator.disk import Disk
 from image_creator.dialog_wizard import start_wizard
 from image_creator.dialog_menu import main_menu
-from image_creator.dialog_util import SMALL_WIDTH, WIDTH, confirm_exit, \
-    Reset, update_background_title
+from image_creator.dialog_util import WIDTH, confirm_exit, Reset, \
+    update_background_title, select_file
 
 PROGNAME = os.path.basename(sys.argv[0])
 
@@ -137,38 +136,6 @@ def create_image(d, media, out, tmp):
     return 0
 
 
-def select_file(d, media):
-    """Select a media file"""
-    if media == '/':
-        return '/'
-
-    default = os.getcwd() + os.sep
-    while 1:
-        if media is not None:
-            if not os.path.exists(media):
-                d.msgbox("The file `%s' you choose does not exist." % media,
-                         width=SMALL_WIDTH)
-            else:
-                mode = os.stat(media).st_mode
-                if not stat.S_ISDIR(mode):
-                    break
-                default = media
-
-        (code, media) = d.fselect(default, 10, 60, extra_button=1,
-                                  title="Please select an input media.",
-                                  extra_label="Bundle Host")
-        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
-            if confirm_exit(d, "You canceled the media selection dialog box."):
-                sys.exit(0)
-            else:
-                media = None
-                continue
-        elif code == d.DIALOG_EXTRA:
-            return '/'
-
-    return media
-
-
 def _dialog_form(self, text, height=20, width=60, form_height=15, fields=[],
                  **kwargs):
     """Display a form box.
@@ -229,7 +196,16 @@ def dialog_main(media, logfile, tmpdir):
     d.setBackgroundTitle('snf-image-creator')
 
     try:
-        media = select_file(d, media)
+        while True:
+            media = select_file(d, init=media, ftype="br", bundle_host=True,
+                                title="Please select an input media.")
+            if media is None:
+                if confirm_exit(
+                        d, "You canceled the media selection dialog box."):
+                    return 0
+                continue
+            break
+
         log = SimpleOutput(False, logfile) if logfile is not None else Output()
         while 1:
             try:
diff --git a/image_creator/dialog_util.py b/image_creator/dialog_util.py
index c716313..6e4c95c 100644
--- a/image_creator/dialog_util.py
+++ b/image_creator/dialog_util.py
@@ -20,6 +20,7 @@ snf-image-creator.
 """
 
 import os
+import stat
 import re
 import json
 from image_creator.output.dialog import GaugeOutput
@@ -30,6 +31,74 @@ SMALL_WIDTH = 60
 WIDTH = 70
 
 
+def select_file(d, **kwargs):
+    """Select a file or directory.
+
+    The following optional arguments can be applied:
+
+    * init: Initial file path. If this path is valid this will be returned
+
+    * ftype: Allowed file types. If the value of this argument is "br" only
+             block devices and regular files are valid. For a list of available
+             file types, see here:
+             http://libguestfs.org/guestfs.3.html#guestfs_readdir
+
+    * title: The dialog box title. The default one is: "Please select a file"
+
+    * bundle_host: This can be True or False. If this is True, an extra
+      "Bundle Host" button will be present if the file selection dialog.
+    """
+
+    type_check = {'b': stat.S_ISBLK,   # Block special
+                  'c': stat.S_ISCHR,   # Char special
+                  'd': stat.S_ISDIR,   # Directory
+                  'f': stat.S_ISFIFO,  # FIFO (named pipe)
+                  'l': stat.S_ISLNK,   # Symbolic link
+                  'r': stat.S_ISREG,   # Regular file
+                  's': stat.S_ISSOCK}  # Socket
+
+    fname = None if "init" not in kwargs else kwargs['init']
+    ftype = set(t for t in kwargs['ftype']) if 'ftype' in kwargs else set('r')
+    title = kwargs['title'] if 'title' in kwargs else 'Please select a file.'
+
+    bundle_host = kwargs['bundle_host'] if 'bundle_host' in kwargs else None
+    extra_button = 1 if bundle_host else 0
+
+    for t in ftype:
+        assert t in type_check, "Invalid ftype: %s" % t
+
+    # This is a special case
+    if bundle_host and fname == os.sep:
+        return os.sep
+
+    default = os.getcwd() + os.sep
+
+    while 1:
+        if fname is not None:
+            if not os.path.exists(fname):
+                d.msgbox("The file `%s' you choose does not exist." % fname,
+                         width=SMALL_WIDTH)
+            else:
+                mode = os.stat(fname).st_mode
+                for i in ftype:
+                    if type_check[i](mode):
+                        return fname
+
+                if stat.S_ISDIR(mode):
+                    default = fname
+                else:
+                    d.msgbox("Invalid input.", width=SMALL_WIDTH)
+
+        (code, fname) = d.fselect(default, 10, 60, extra_button=extra_button,
+                                  title=title, extra_label="Bundle Host")
+        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
+            return None
+        elif code == d.DIALOG_EXTRA:
+            return os.sep
+
+    return fname
+
+
 def update_background_title(session):
     """Update the background title of the dialog page"""
     d = session['dialog']
-- 
GitLab