Started implementing support for the Mercurial archive function.

Wed, 24 Jul 2013 19:58:04 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Wed, 24 Jul 2013 19:58:04 +0200
changeset 2820
642c1f3c23c8
parent 2819
3e9da38244cd
child 2821
459cc954bea8

Started implementing support for the Mercurial archive function.

E5Gui/E5Completers.py file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/HgArchiveDialog.py file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/HgArchiveDialog.ui file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/ProjectHelper.py file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/hg.py file | annotate | diff | comparison | revisions
eric5.e4p file | annotate | diff | comparison | revisions
--- a/E5Gui/E5Completers.py	Wed Jul 24 19:43:44 2013 +0200
+++ b/E5Gui/E5Completers.py	Wed Jul 24 19:58:04 2013 +0200
@@ -12,6 +12,7 @@
 
 from Globals import isWindowsPlatform
 
+# TODO: replace obsoleted QDirModel by QFileSystemModel
 
 class E5FileCompleter(QCompleter):
     """
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/VcsPlugins/vcsMercurial/HgArchiveDialog.py	Wed Jul 24 19:58:04 2013 +0200
@@ -0,0 +1,145 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2013 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to enter the archive data.
+"""
+
+from PyQt4.QtCore import pyqtSlot, QFileInfo
+from PyQt4.QtGui import QDialog, QDialogButtonBox
+
+from E5Gui.E5Completers import E5FileCompleter, E5DirCompleter
+from E5Gui import E5FileDialog
+
+from .Ui_HgArchiveDialog import Ui_HgArchiveDialog
+
+import Utilities
+
+
+class HgArchiveDialog(QDialog, Ui_HgArchiveDialog):
+    """
+    Class implementing a dialog to enter the archive data.
+    """
+    def __init__(self, vcs, parent=None):
+        """
+        Constructor
+        
+        @param vcs reference to the Mercurial object (Hg)
+        @param parent reference to the parent widget (QWidget)
+        """
+        super().__init__(parent)
+        self.setupUi(self)
+        
+        self.__archiveFileCompleter = E5FileCompleter()
+        self.__archiveDirCompleter = E5DirCompleter()
+        self.__activeCompleter = self.__archiveFileCompleter
+        self.archiveEdit.setCompleter(self.__activeCompleter)
+        
+        self.typeComboBox.addItem(self.trUtf8("Detect Automatically"), "")
+        self.typeComboBox.addItem(self.trUtf8("Directory of Files"), "files")
+        self.typeComboBox.addItem(self.trUtf8("Uncompressed TAR-Archive"), "tar")
+        self.typeComboBox.addItem(self.trUtf8("Bzip2 compressed TAR-Archive"), "tbz2")
+        self.typeComboBox.addItem(self.trUtf8("Gzip compressed TAR-Archive"), "tgz")
+        self.typeComboBox.addItem(self.trUtf8("Uncompressed ZIP-Archive"), "uzip")
+        self.typeComboBox.addItem(self.trUtf8("Compressed ZIP-Archive"), "zip")
+        
+        self.__unixFileFilters = [
+            self.trUtf8("Bzip2 compressed TAR-Archive (*.tar.bz2)"),
+            self.trUtf8("Gzip compressed TAR-Archive (*.tar.gz)"),
+            self.trUtf8("Uncompressed TAR-Archive (*.tar)"),
+        ]
+        self.__windowsFileFilters = [
+            self.trUtf8("Compressed ZIP-Archive (*.zip)"),
+            self.trUtf8("Uncompressed ZIP-Archive (*.uzip)")
+        ]
+        if Utilities.isWindowsPlatform():
+            self.__fileFilters = ";;".join(
+                self.__windowsFileFilters + self.__unixFileFilters)
+        else:
+            self.__fileFilters = ";;".join(
+                self.__unixFileFilters + self.__windowsFileFilters)
+        self.__fileFilters += ";;" + self.trUtf8("All Files (*)")
+        
+        self.subReposCheckBox.setEnabled(vcs.hasSubrepositories())
+        
+        self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)
+        
+        self.__projectPath = \
+            vcs.getPlugin().getProjectHelper().getProject().getProjectPath()
+    
+    @pyqtSlot(str)
+    def on_archiveEdit_textChanged(self, archive):
+        """
+        Private slot to handle changes of the archive name.
+        """
+        self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(archive != "")
+    
+    @pyqtSlot()
+    def on_archiveButton_clicked(self):
+        """
+        Private slot to select the archive name via a file selection dialog.
+        """
+        type_ = self.typeComboBox.itemData(self.typeComboBox.currentIndex())
+        
+        archive = Utilities.fromNativeSeparators(self.archiveEdit.text())
+        if not archive:
+            archive = self.__projectPath
+        
+        if type_ == "files":
+            archive = E5FileDialog.getExistingDirectory(
+                self,
+                self.trUtf8("Select Archive Directory"),
+                archive,
+                E5FileDialog.Options(E5FileDialog.ShowDirsOnly))
+        else:
+            archive, selectedFilter = E5FileDialog.getSaveFileNameAndFilter(
+                self,
+                self.trUtf8("Select Archive File"),
+                archive,
+                self.__fileFilters,
+                None,
+                E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite))
+            if archive:
+                ext = QFileInfo(archive).suffix()
+                if not ext:
+                    ex = selectedFilter.split("(*")[1].split(")")[0]
+                    if ex:
+                        archive += ex
+        
+        if archive:
+            self.archiveEdit.setText(Utilities.toNativeSeparators(archive))
+    
+    @pyqtSlot(int)
+    def on_typeComboBox_activated(self, index):
+        """
+        Private slot to react on changes of the selected archive type.
+        
+        @param index index of the selected type (integer)
+        """
+        type_ = self.typeComboBox.itemData(index)
+        if type_ == "files":
+            if self.__activeCompleter != self.__archiveDirCompleter:
+                self.__activeCompleter = self.__archiveDirCompleter
+                self.archiveEdit.setCompleter(self.__activeCompleter)
+        else:
+            # TODO: add name filter to completer based upon selected type
+            if self.__activeCompleter != self.__archiveFileCompleter:
+                self.__activeCompleter = self.__archiveFileCompleter
+                self.archiveEdit.setCompleter(self.__activeCompleter)
+    
+    def getData(self):
+        """
+        Public method to retrieve the data.
+        
+        @return tuple giving the archive name (string), the archive type (string),
+            the directory prefix 8string) and a flag indicating to recurse into
+            subrepositories (boolean)
+        """
+        return (
+            self.archiveEdit.text(),
+            self.typeComboBox.itemData(self.typeComboBox.currentIndex()),
+            self.prefixEdit.text(),
+            self.subReposCheckBox.isChecked(),
+        )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/VcsPlugins/vcsMercurial/HgArchiveDialog.ui	Wed Jul 24 19:58:04 2013 +0200
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>HgArchiveDialog</class>
+ <widget class="QDialog" name="HgArchiveDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>145</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Mercurial Archive</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0">
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>Archive:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="1">
+    <widget class="QLineEdit" name="archiveEdit">
+     <property name="toolTip">
+      <string>Enter the file name of the archive</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="2">
+    <widget class="QPushButton" name="archiveButton">
+     <property name="toolTip">
+      <string>Press to select the archive file name via a file selection dialog</string>
+     </property>
+     <property name="text">
+      <string>...</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <widget class="QLabel" name="label_3">
+     <property name="text">
+      <string>Type:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="1" colspan="2">
+    <widget class="QComboBox" name="typeComboBox">
+     <property name="toolTip">
+      <string>Select the archive type</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="0">
+    <widget class="QLabel" name="label_2">
+     <property name="text">
+      <string>Prefix:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="1" colspan="2">
+    <widget class="QLineEdit" name="prefixEdit">
+     <property name="toolTip">
+      <string>Enter the directory prefix for the files in the archive</string>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="0" colspan="3">
+    <widget class="QCheckBox" name="subReposCheckBox">
+     <property name="toolTip">
+      <string>Select to recurse into subrepositories</string>
+     </property>
+     <property name="text">
+      <string>Include Subrepositories</string>
+     </property>
+    </widget>
+   </item>
+   <item row="4" column="0" colspan="3">
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>archiveEdit</tabstop>
+  <tabstop>archiveButton</tabstop>
+  <tabstop>typeComboBox</tabstop>
+  <tabstop>prefixEdit</tabstop>
+  <tabstop>subReposCheckBox</tabstop>
+  <tabstop>buttonBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>HgArchiveDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>HgArchiveDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
--- a/Plugins/VcsPlugins/vcsMercurial/ProjectHelper.py	Wed Jul 24 19:43:44 2013 +0200
+++ b/Plugins/VcsPlugins/vcsMercurial/ProjectHelper.py	Wed Jul 24 19:58:04 2013 +0200
@@ -917,6 +917,20 @@
         ))
         self.hgRemoveSubreposAct.triggered[()].connect(self.__hgRemoveSubrepositories)
         self.actions.append(self.hgRemoveSubreposAct)
+        
+        self.hgArchiveAct = E5Action(self.trUtf8('Create unversioned archive'),
+                UI.PixmapCache.getIcon("vcsExport.png"),
+                self.trUtf8('Create unversioned archive...'),
+                0, 0, self, 'mercurial_archive')
+        self.hgArchiveAct.setStatusTip(self.trUtf8(
+            'Create an unversioned archive from the repository'
+        ))
+        self.hgArchiveAct.setWhatsThis(self.trUtf8(
+            """<b>Create unversioned archive...</b>"""
+            """<p>This creates an unversioned archive from the repository.</p>"""
+        ))
+        self.hgArchiveAct.triggered[()].connect(self.__hgArchive)
+        self.actions.append(self.hgArchiveAct)
     
     def initMenu(self, menu):
         """
@@ -953,6 +967,8 @@
         
         specialsMenu = QMenu(self.trUtf8("Specials"), menu)
         specialsMenu.setTearOffEnabled(True)
+        specialsMenu.addAction(self.hgArchiveAct)
+        specialsMenu.addSeparator()
         specialsMenu.addAction(self.hgPushForcedAct)
         specialsMenu.addSeparator()
         specialsMenu.addAction(self.hgServeAct)
@@ -1432,3 +1448,9 @@
         Private slot to show a working directory summary.
         """
         self.vcs.hgSummary()
+    
+    def __hgArchive(self):
+        """
+        Private slot to create an unversioned archive from the repository.
+        """
+        self.vcs.hgArchive()
--- a/Plugins/VcsPlugins/vcsMercurial/hg.py	Wed Jul 24 19:43:44 2013 +0200
+++ b/Plugins/VcsPlugins/vcsMercurial/hg.py	Wed Jul 24 19:58:04 2013 +0200
@@ -2739,6 +2739,39 @@
             self.checkVCSStatus()
         return res
     
+    def hgArchive(self):
+        """
+        Public method to create an unversioned archive from the repository.
+        """
+        # find the root of the repo
+        repodir = self.__projectHelper.getProject().getProjectPath()
+        while not os.path.isdir(os.path.join(repodir, self.adminDir)):
+            repodir = os.path.dirname(repodir)
+            if os.path.splitdrive(repodir)[1] == os.sep:
+                return
+        
+        from .HgArchiveDialog import HgArchiveDialog
+        dlg = HgArchiveDialog(self)
+        if dlg.exec_() == QDialog.Accepted:
+            archive, type_, prefix, subrepos = dlg.getData()
+            
+            args = []
+            args.append("archive")
+            if type_:
+                args.append("--type")
+                args.append(type_)
+            if prefix:
+                args.append("--prefix")
+                args.append(prefix)
+            if subrepos:
+                args.append("--subrepos")
+            args.append(archive)
+            
+            dia = HgDialog(self.trUtf8("Create Unversioned Archive"), self)
+            res = dia.startProcess(args, repodir)
+            if res:
+                dia.exec_()
+    
     ############################################################################
     ## Methods to deal with subrepositories are below.
     ############################################################################
--- a/eric5.e4p	Wed Jul 24 19:43:44 2013 +0200
+++ b/eric5.e4p	Wed Jul 24 19:58:04 2013 +0200
@@ -1106,6 +1106,7 @@
     <Source>ThirdParty/Jasy/jasy/js/tokenize/Lang.py</Source>
     <Source>Plugins/VcsPlugins/vcsMercurial/ConfigurationPage/MercurialUserDataDialog.py</Source>
     <Source>Plugins/VcsPlugins/vcsMercurial/HgSummaryDialog.py</Source>
+    <Source>Plugins/VcsPlugins/vcsMercurial/HgArchiveDialog.py</Source>
   </Sources>
   <Forms>
     <Form>PyUnit/UnittestDialog.ui</Form>
@@ -1426,6 +1427,7 @@
     <Form>Plugins/WizardPlugins/QRegularExpressionWizard/QRegularExpressionWizardRepeatDialog.ui</Form>
     <Form>Plugins/VcsPlugins/vcsMercurial/ConfigurationPage/MercurialUserDataDialog.ui</Form>
     <Form>Plugins/VcsPlugins/vcsMercurial/HgSummaryDialog.ui</Form>
+    <Form>Plugins/VcsPlugins/vcsMercurial/HgArchiveDialog.ui</Form>
   </Forms>
   <Translations>
     <Translation>i18n/eric5_cs.ts</Translation>

eric ide

mercurial