On Wed, Jul 30, 2008 at 08:56:19PM +0200, Marc 'HE' Brockschmidt wrote: > Roberto C. Sánchez <[EMAIL PROTECTED]> writes: > > As of about one week ago, version 1.3 is now available from upstream > > [2]. This version works with all the changes to SourceForge's site. > > My first instinct was to simply request removal of the package. > > However, that is undesirable as it has already shipped with a stable > > release (version 1.1-1 is in Etch). Removal from Lenny would leave Etch > > users without any sort of upgrade path. Leaving the current version in > > Lenny would, however, result in a package that is completely broken for > > Lenny's entire life cycle. > > Pushing an untested package into the frozen lenny is not an option, so > removal seems to be the most reasonable course. > OK. Based on #492933, I asked for a removal from testing. After that, I asked about the possibility for inclusion in Lenny on #debian-release and the impression that I got from vorlon and dato was that if the changes were limited, that it would be possible to get an exception.
So, I and another user have tested the updated package. Have a look at the log for #492933 for the user's comments about the package working for him. I have also verified that it works for me. I have attached the debdiff between 1.1-4 (currently in Sid and it was in Lenny until yesterday) and 1.3-1 (please note that upstream never released version 1.2, he went from 1.1 a little over two years ago to 1.3 just last week). Please consider this package for inclusion in Lenny (the package is currently in INCOMING). Regards, -Roberto -- Roberto C. Sánchez http://people.connexer.com/~roberto http://www.connexer.com
diff -Nru releaseforge-1.1/CHANGELOG.txt releaseforge-1.3/CHANGELOG.txt --- releaseforge-1.1/CHANGELOG.txt 2006-06-15 05:51:53.000000000 -0400 +++ releaseforge-1.3/CHANGELOG.txt 2008-06-12 00:12:41.000000000 -0400 @@ -1,6 +1,17 @@ ReleaseForge ChangeLog ---------------------- +version 1.3: + *) added support for sftp + *) removed support for ftp + +version 1.2: + *) uploading release notes and change log now attempts to use tempfiles to transmit + the data as multipart encodings rather than inline text (if unable to create the temp files + ReleaseForge will fallback to the old mechanism). This should allow encoded entities (such as + the ampersand) to be transmitted properly. + *) ReleaseForge will now automatically retry failed https connections + version 1.1: *) added re-guess file attributes button *) fix: disabled chunking when selecting files to include in a release which caused the diff -Nru /tmp/user/2000/X5m6gbvF7f/releaseforge-1.1/MANIFEST.in /tmp/user/2000/EZty4Ck08i/releaseforge-1.3/MANIFEST.in --- releaseforge-1.1/MANIFEST.in 2006-04-24 12:46:24.000000000 -0400 +++ releaseforge-1.3/MANIFEST.in 2008-07-07 12:17:28.000000000 -0400 @@ -1,7 +1,5 @@ recursive-include help *.html recursive-include help *.png -######recursive-include translations * -######recursive-include scripts * include setup.cfg include images/*.png include images/*.ico @@ -9,6 +7,7 @@ include LICENSE.txt include README.txt include CHANGELOG.txt +include RELEASE_NOTES.txt include ReleaseForge/*.ui include ReleaseForge/*.py include releaseforge.pro diff -Nru /tmp/user/2000/X5m6gbvF7f/releaseforge-1.1/PKG-INFO /tmp/user/2000/EZty4Ck08i/releaseforge-1.3/PKG-INFO --- releaseforge-1.1/PKG-INFO 2006-06-15 06:02:06.000000000 -0400 +++ releaseforge-1.3/PKG-INFO 2008-07-07 12:17:53.000000000 -0400 @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: releaseforge -Version: 1.1 +Version: 1.3 Summary: ReleaseForge is a utility designed for the administrators and release engineers of SourceForge projects. Home-page: http://releaseforge.sourceforge.net Author: Phil Schwartz diff -Nru /tmp/user/2000/X5m6gbvF7f/releaseforge-1.1/RELEASE_NOTES.txt /tmp/user/2000/EZty4Ck08i/releaseforge-1.3/RELEASE_NOTES.txt --- releaseforge-1.1/RELEASE_NOTES.txt 1969-12-31 19:00:00.000000000 -0500 +++ releaseforge-1.3/RELEASE_NOTES.txt 2008-07-07 12:16:27.000000000 -0400 @@ -0,0 +1,19 @@ +Version 1.3: +============ + +Sourceforge has recently deprecated the FTP upload mechanism. This policy change cripples ReleaseForge prior to 1.3. + +ReleaseForge 1.3 now uploads files to Sourceforge via SFTP (one of the new supported methods). + +Prior to running ReleaseForge 1.3 you will need to obtain Paramiko v1.74 or greater. +ReleaseFroge uses paramiko module for uploading files to SourceForge via SFTP. [Special thanks to Robey Pointer for adding the +patch required for ReleaseForge]. + +Paramiko can be downloaded from: + +http://www.lag.net/paramiko/ + +Make sure you obtain 1.74 or greater. Versions prior to 1.74 will not work. + +Once paramiko is installed, ReleaseForge should be able to upload files to Sourceforge via SFTP using the same login credentials +for accessing the Sourceforge web interface. diff -Nru /tmp/user/2000/X5m6gbvF7f/releaseforge-1.1/ReleaseForge/MultipartPostHandler.py /tmp/user/2000/EZty4Ck08i/releaseforge-1.3/ReleaseForge/MultipartPostHandler.py --- releaseforge-1.1/ReleaseForge/MultipartPostHandler.py 1969-12-31 19:00:00.000000000 -0500 +++ releaseforge-1.3/ReleaseForge/MultipartPostHandler.py 2006-07-01 17:30:14.000000000 -0400 @@ -0,0 +1,128 @@ +#!/usr/bin/python + +#### +# 02/2006 Will Holcomb <[EMAIL PROTECTED]> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +""" +Usage: + Enables the use of multipart/form-data for posting forms + +Inspirations: + Upload files in python: + http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/146306 + urllib2_file: + Fabien Seisen: <[EMAIL PROTECTED]> + +Example: + import MultipartPostHandler, urllib2, cookielib + + cookies = cookielib.CookieJar() + opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookies), + MultipartPostHandler.MultipartPostHandler) + params = { "username" : "bob", "password" : "riviera", + "file" : open("filename", "rb") } + opener.open("http://wwww.bobsite.com/upload/", params) + +Further Example: + The main function of this file is a sample which downloads a page and + then uploads it to the W3C validator. +""" + +import urllib +import urllib2 +import mimetools, mimetypes +import os, stat + +class Callable: + def __init__(self, anycallable): + self.__call__ = anycallable + +class MultipartPostHandler(urllib2.BaseHandler): + handler_order = urllib2.HTTPHandler.handler_order - 10 # needs to run first + + def http_request(self, request): + data = request.get_data() + if data is not None and type(data) != str: + v_files = [] + v_vars = [] + try: + for(key, value) in data.items(): + if type(value) == file: + v_files.append((key, value)) + else: + v_vars.append((key, value)) + except TypeError: + systype, value, traceback = sys.exc_info() + raise TypeError, "not a valid non-string sequence or mapping object", traceback + + if len(v_files) == 0: + data = urllib.urlencode(v_vars) + else: + boundary, data = self.multipart_encode(v_vars, v_files) + contenttype = 'multipart/form-data; boundary=%s' % boundary + if request.has_header('Content-type'): + pass # print "Replacing %s with %s" % (request.get_header('content-type'), contenttype) + request.add_unredirected_header('Content-type', contenttype) + + request.add_data(data) + + return request + + def multipart_encode(vars, files, boundary = None, buffer = None): + if boundary is None: + boundary = mimetools.choose_boundary() + if buffer is None: + buffer = '' + for(key, value) in vars: + buffer += '--%s\r\n' % boundary + buffer += 'Content-Disposition: form-data; name="%s"' % key + buffer += '\r\n\r\n' + value + '\r\n' + for(key, fd) in files: + file_size = os.fstat(fd.fileno())[stat.ST_SIZE] + filename = fd.name.split('/')[-1] + contenttype = mimetypes.guess_type(filename)[0] or 'application/octet-stream' + buffer += '--%s\r\n' % boundary + buffer += 'Content-Disposition: form-data; name="%s"; filename="%s"\r\n' % (key, filename) + buffer += 'Content-Type: %s\r\n' % contenttype + # buffer += 'Content-Length: %s\r\n' % file_size + fd.seek(0) + buffer += '\r\n' + fd.read() + '\r\n' + buffer += '--%s--\r\n\r\n' % boundary + return boundary, buffer + multipart_encode = Callable(multipart_encode) + + https_request = http_request + +def main(): + import tempfile, sys + + validatorURL = "http://validator.w3.org/check" + opener = urllib2.build_opener(MultipartPostHandler) + + def validateFile(url): + temp = tempfile.mkstemp(suffix=".html") + os.write(temp[0], opener.open(url).read()) + params = { "ss" : "0", # show source + "doctype" : "Inline", + "uploaded_file" : open(temp[1], "rb") } + print opener.open(validatorURL, params).read() + os.remove(temp[1]) + + if len(sys.argv[1:]) > 0: + for arg in sys.argv[1:]: + validateFile(arg) + else: + validateFile("http://www.google.com") + +if __name__=="__main__": + main() diff -Nru /tmp/user/2000/X5m6gbvF7f/releaseforge-1.1/ReleaseForge/constants.py /tmp/user/2000/EZty4Ck08i/releaseforge-1.3/ReleaseForge/constants.py --- releaseforge-1.1/ReleaseForge/constants.py 2006-04-21 16:31:00.000000000 -0400 +++ releaseforge-1.3/ReleaseForge/constants.py 2008-06-12 21:33:57.000000000 -0400 @@ -12,8 +12,10 @@ LOGGER_CONFIG_FILENAME = "logger.ini" -SF_FTP_SERVER = "upload.sourceforge.net" -SF_FTP_DIRECTORY = "incoming" +SF_SFTP_SERVER = "frs.sourceforge.net" +SF_SFTP_PORT = 22 +SF_SFTP_DIRECTORY = "uploads" + SF_WARNING = """ The follwing files could not be added to your release diff -Nru /tmp/user/2000/X5m6gbvF7f/releaseforge-1.1/ReleaseForge/ftp.py /tmp/user/2000/EZty4Ck08i/releaseforge-1.3/ReleaseForge/ftp.py --- releaseforge-1.1/ReleaseForge/ftp.py 2005-12-16 17:47:12.000000000 -0500 +++ releaseforge-1.3/ReleaseForge/ftp.py 1969-12-31 19:00:00.000000000 -0500 @@ -1,44 +0,0 @@ -from ftplib import FTP - -class FTP_(FTP): - def storbinary(self, cmd, fp, blocksize=8192, callback=None): - '''Store a file in binary mode and optionally - use a callback func to provide a tuple containing - number of bytes transmitted to the ftp server and total size - ''' - self.voidcmd('TYPE I') - conn = self.transfercmd(cmd) - if callback: - totalsent = 0 - fp.seek(0L, 2) # go to file end - totalsize = fp.tell() - fp.seek(0L, 0) # go to file start - - while 1: - buf = fp.read(blocksize) - if not buf: break - conn.sendall(buf) - if callback: - callback( (totalsent, totalsize) ) - totalsent += blocksize - conn.close() - return self.voidresp() - - -if __name__ == '__main__': - def func(transmitted): print "transmitted:", transmitted - - import sys - from constants import SF_FTP_SERVER, SF_FTP_DIRECTORY - - filename = sys.argv[1] - f = open(filename, "rb") - - ftp = FTP_() - ftp.connect(SF_FTP_SERVER) - ftp.getwelcome() - - ftp.login("ftp", "releaseforge") - ftp.cwd(SF_FTP_DIRECTORY) - ftp.storbinary('STOR ' + filename, f, callback=func) - ftp.close() diff -Nru /tmp/user/2000/X5m6gbvF7f/releaseforge-1.1/ReleaseForge/messageQueue.py /tmp/user/2000/EZty4Ck08i/releaseforge-1.3/ReleaseForge/messageQueue.py --- releaseforge-1.1/ReleaseForge/messageQueue.py 2005-12-16 17:47:12.000000000 -0500 +++ releaseforge-1.3/ReleaseForge/messageQueue.py 2008-06-12 21:30:14.000000000 -0400 @@ -22,4 +22,4 @@ mainMessageQueue = MessageQueue() progressMessageQueue = MessageQueue() freshmeatMessageQueue = MessageQueue() -ftpProgressQueue = MessageQueue() +sftpProgressQueue = MessageQueue() diff -Nru /tmp/user/2000/X5m6gbvF7f/releaseforge-1.1/ReleaseForge/releaseWizard.py /tmp/user/2000/EZty4Ck08i/releaseforge-1.3/ReleaseForge/releaseWizard.py --- releaseforge-1.1/ReleaseForge/releaseWizard.py 2006-06-15 05:14:06.000000000 -0400 +++ releaseforge-1.3/ReleaseForge/releaseWizard.py 2008-06-12 21:31:35.000000000 -0400 @@ -6,7 +6,7 @@ import os from ReleaseDataVO import ReleaseDataVO from FileVO import FileVO -from messageQueue import progressMessageQueue, ftpProgressQueue +from messageQueue import progressMessageQueue, sftpProgressQueue from workerThread import WorkerThread from help import Help import time @@ -79,9 +79,9 @@ self.connect(self.timer, SIGNAL("timeout()"), self.getProgressMsg) - self.ftp_timer = QTimer(self) - self.connect(self.ftp_timer, SIGNAL("timeout()"), - self.update_ftp_progress) + self.sftp_timer = QTimer(self) + self.connect(self.sftp_timer, SIGNAL("timeout()"), + self.update_sftp_progress) self.connect(self, SIGNAL("selected(const QString &)"), self.pageChanged) self.releaseNameEdited(self.newReleaseNameLineEdit.text()) @@ -200,12 +200,12 @@ def show_file_progress(self, show): debug("show_file_progress: %s", show) if show: - self.ftp_timer.start(50, False) + self.sftp_timer.start(50, False) self.fileTextLabel.show() self.fileProgressBar.setProgress(-1) self.fileProgressBar.show() else: - self.ftp_timer.stop() + self.sftp_timer.stop() self.fileTextLabel.hide() self.fileProgressBar.hide() @@ -664,7 +664,7 @@ release_notes = data_tuple[0] change_log = data_tuple[1] files = data_tuple[2] - + self.releaseNotesTextEdit.setText(from_utf8(release_notes)) self.changeLogTextEdit.setText(from_utf8(change_log)) self.setNextEnabled(self.page(WIZARD_PAGE_RELEASE_NAME), False) @@ -763,13 +763,19 @@ # populate the progress label with it. msg = progressMessageQueue.get() if msg: - self.progressTextLabel.setText(msg) - self.incrementProgressBar() + self.progressTextLabel.setText(msg) + if not msg.startswith("Retry: "): + self.incrementProgressBar() +# else: +# self.decrementProgressBar(1) def incrementProgressBar(self, increment=1): self.progressBar.setProgress(self.progressBar.progress() + increment) + def decrementProgressBar(self, decrement=1): + self.progressBar.setProgress(self.progressBar.progress() - decrement) + def isCancelled(self): return self.cancelled @@ -1054,7 +1060,7 @@ def error(self, msg): self.timer.stop() - self.ftp_timer.stop() + self.sftp_timer.stop() page = self.page(WIZARD_PAGE_PROGRESS) self.progressTextLabel.setText(msg) self.setFinishEnabled(page, False) @@ -1065,7 +1071,7 @@ def complete(self, data): self.timer.stop() - self.ftp_timer.stop() + self.sftp_timer.stop() page = self.page(WIZARD_PAGE_PROGRESS) if self.create: self.progressTextLabel.setText("Successfully created new release") @@ -1107,10 +1113,10 @@ self.notifyTextLabel.setEnabled(False) - def update_ftp_progress(self): + def update_sftp_progress(self): # read the message queue. If an item exists, # populate the progress label with it. - progress_tuple = ftpProgressQueue.get() + progress_tuple = sftpProgressQueue.get() #debug("update_ftp_progress: %s", progress_tuple) if progress_tuple: if progress_tuple == (True, True): diff -Nru /tmp/user/2000/X5m6gbvF7f/releaseforge-1.1/ReleaseForge/sfcomm.py /tmp/user/2000/EZty4Ck08i/releaseforge-1.3/ReleaseForge/sfcomm.py --- releaseforge-1.1/ReleaseForge/sfcomm.py 2006-06-15 05:49:44.000000000 -0400 +++ releaseforge-1.3/ReleaseForge/sfcomm.py 2008-07-07 09:51:03.000000000 -0400 @@ -1,7 +1,7 @@ from workerThread import WorkerThread from sfurls import * from sfregex import * -from constants import SF_COOKIE_FILENAME, SF_FTP_SERVER, SF_FTP_DIRECTORY +from constants import SF_COOKIE_FILENAME, SF_SFTP_SERVER, SF_SFTP_DIRECTORY, SF_SFTP_PORT from ProjectVO import ProjectVO from PackageVO import PackageVO @@ -12,14 +12,19 @@ except: # python2.3 compatibility from python24.urllib2 import build_opener, HTTPCookieProcessor, ProxyHandler +import MultipartPostHandler import logging -from messageQueue import mainMessageQueue, progressMessageQueue, ftpProgressQueue +from messageQueue import mainMessageQueue, progressMessageQueue, sftpProgressQueue import os, sys -from ftp import FTP_ +import paramiko import time from constants import SF_RESPONSE_CHUNK_SIZE +from types import StringType +import tempfile debug = logging.getLogger("sfcomm").debug +info = logging.getLogger("sfcomm").info +warn = logging.getLogger("sfcomm").warn error = logging.getLogger("sfcomm").error exception = logging.getLogger("sfcomm").exception @@ -43,6 +48,18 @@ TRUNCATE_POST = 1024 +class RetryException(Exception): pass + +def unescape_entities(s): + # replace & < > " in s with their text counterparts + if not s: return s + s = s.replace("&", "&") + s = s.replace("<", "<") + s = s.replace(">", ">") + s = s.replace(""", '"') + return s + + class SFComm: def __init__(self, data_path, proxy=None): self.cookie_file = os.path.join(data_path, SF_COOKIE_FILENAME) @@ -64,15 +81,17 @@ queue=progressMessageQueue, addl_headers=None, ok_status=None, + post_as_multipart=None, + retry=True, dbg=None): # # parameters: # url: url to retrieve - # post_encoded: the encoded query string sent to SF + # post_encoded: the (preferably) encoded query string sent to SF # queue: the python Queue that status information will be sent to # addl_headers: any additional headers that need to be passed to SF # ok_status: a string as described below. - # + # post_as_multipart: post form data with enctype: multipart/form-data # returns a tuple containing the data returned from SF and the status. # # If ok_status is provided, the status returned is True if the @@ -81,26 +100,59 @@ # # If ok_status is None, status is always True and data will not be truncated # + # If retry is True, then this is the first attempt and if it fails this transaction + # will be retried. + # # return tuple form: (data, status) # data = "" ok = True try: debug("Fetching: %s", url) - if post_encoded: + if post_encoded and type(post_encoded) is StringType: if len(post_encoded) > TRUNCATE_POST: truncated = "..." else: truncated = "" + debug("posted: %s%s", post_encoded[:TRUNCATE_POST], truncated) - queue.put("Fetching: %s" % url) + if not retry: + # has already been tried, this is the retry attempt + queue.put("Retry: %s" % url) + else: + # has not be attempted yet... will retry if this fails + queue.put("Fetching: %s" % url) cj = cookielib.MozillaCookieJar() cj.load(self.cookie_file, True) - opener = build_opener(HTTPCookieProcessor(cj)) + if post_as_multipart: + # enctype: multipart/form-data + opener = build_opener(HTTPCookieProcessor(cj), + MultipartPostHandler.MultipartPostHandler) + else: + opener = build_opener(HTTPCookieProcessor(cj)) + if addl_headers: opener.addheaders = addl_headers - r = opener.open(url, post_encoded) + try: + r = opener.open(url, post_encoded) + except Exception, e: + exception(e) + error("failed posting: %s", post_encoded) + if retry: + error("retrying last action") + return self.fetch_url(url, + post_encoded, + queue, + addl_headers, + ok_status, + post_as_multipart, + False, + dbg) + else: + error("giving up") + raise RetryException("Retry failed... giving up") + # debug("r methods: %s", dir(r)) # cj.save(self.cookie_file, True) if not ok_status: @@ -129,8 +181,10 @@ r.close() if dbg: debug("Done") #debug("length: %ld - url: %s", len(data), url) + except RetryException, e: + raise except Exception, e: - print e + exception(e) if dbg: debug("DATA: %s", data) return data, ok @@ -140,6 +194,8 @@ def login(self, username, password, return_to=None): # returns a set of projects for the given username/password # or None + self.username = username # used by sftp + self.password = password # used by sftp debug("Attempting to login to SourceForge") form = {'form_loginname': username, 'form_pw': password, @@ -168,13 +224,14 @@ cj.save(self.cookie_file, True, True) # ignore discard! ignore expires + projects = set() + data = r.read() idx = data.find("Invalid Password or User Name") if idx != -1: debug("Could not login") return projects - projects = set() #debug(data) project_tuples = PROJECTS_FROM_MY_PROJECTS.findall(data) for pt in project_tuples: @@ -186,7 +243,6 @@ return projects - def get_packages(self, group_id): url = "%s=%s" % (EDIT_PACKAGE_BASE_URL, group_id) packages = set() @@ -237,32 +293,7 @@ mainMessageQueue.put("You do not have the proper permissions") return False else: return True - - def add_release(self, group_id, package_id, name): - url = "%s?package_id=%s&group_id=%s" % (NEW_RELEASE_URL, - package_id, - group_id) - form = {'package_id': package_id, - 'group_id': group_id, - 'release_name': name, - 'newrelease': 'yes', - 'submit': 'Create This Release'} - - data = self.fetch_url(url, urlencode(form))[0] - #print url - m = GET_RELEASE_ID.search(data) - if m: - return m.group("releaseid") - else: - if data.find("Error creating Project object") != -1: - progressMessageQueue.put("Error creating Project object") - elif data.find("Login to SourceForge.net") != -1: - progressMessageQueue.put("Login required?") - #print data - else: - progressMessageQueue.put("Error creating new release") - return None def get_releases(self, group_id, package_id): url = "%s?group_id=%s&package_id=%s" % (EDIT_RELEASE_URL, @@ -293,8 +324,8 @@ m = GET_NOTES_AND_LOG.search(data) if m: - release_notes = m.group("releasenotes") - change_log = m.group("changelog") + release_notes = unescape_entities(m.group("releasenotes")) + change_log = unescape_entities(m.group("changelog")) filedata = GET_FILE_NAMES_ETC.findall(data) files = [] @@ -313,6 +344,7 @@ debug("file: %s - %s - %s - %s", fileid, filename, processor, filetype) debug("edit release - files: %s", files) + return (release_notes, change_log, files) @@ -338,8 +370,6 @@ return result - - def add_release(self, group_id, package_id, name): url = "%s?package_id=%s&group_id=%s" % (NEW_RELEASE_URL, package_id, @@ -363,6 +393,7 @@ #print data else: progressMessageQueue.put("Error creating new release") + error("error creating new release (could not find releaseid): " + data) return None @@ -383,19 +414,92 @@ 'status_id': status_id, 'uploaded_notes': '', 'uploaded_changes': '', - 'release_notes': release_notes, - 'release_changes': change_log, + 'release_notes': '', + 'release_changes': '', 'preformatted': '1', 'submit': 'Submit/Refresh' } - ok = self.fetch_url(url, - urlencode(form), - ok_status="Data Saved")[1] + + # attempt to create temp files to store the release notes and change log + # if unable to do so or if it cannot completed the task fallback to old behavior + # and simply post the text of each as-is. + try: + release_notes_fp, release_notes_path = tempfile.mkstemp(prefix="rf-", text=True) + os.write(release_notes_fp, "%s\n" % release_notes) + os.close(release_notes_fp) + form['uploaded_notes'] = open(release_notes_path, "r") + except: + warn("could not create tempfile for release_notes, reverting to old implementation") + release_notes_path = "" + + try: + change_log_fp, change_log_path = tempfile.mkstemp(prefix="rf-", text=True) + os.write(change_log_fp, "%s\n" % change_log) + os.close(change_log_fp) + form['uploaded_changes'] = open(change_log_path, "r") + except: + warn("could not create tempfile for change_log, reverting to old implementation") + change_log_path = "" + + if not change_log_path or not release_notes_path: + return self.edit_release_step1_fallback(group_id, package_id, release_id, + name, release_notes, change_log, status) + + try: + ok = self.fetch_url(url, + form, # encoded by MultipartPostHandler + post_as_multipart=True, + ok_status="Data Saved")[1] + except: + ok = self.edit_release_step1_fallback(group_id, package_id, release_id, + name, release_notes, change_log, status) + + # if the temp files were created, remove them now + if release_notes_path: + try: os.remove(release_notes_path) + except: pass + + if change_log_path: + try: os.remove(change_log_path) + except: pass + return ok - #if data.find("Data Saved") != -1: return True - #else: return False + def edit_release_step1_fallback(self, group_id, package_id, release_id, + name, release_notes, change_log, status='active'): + url = EDIT_RELEASE_URL + if status.lower() == 'active': status_id = '1' + else: status_id = '3' + + warn("using (post) fallback method... html entities will be munged") + + form = {'package_id': package_id, + 'new_package_id': package_id, + 'group_id': group_id, + 'release_id': release_id, + 'release_name': name, + 'release_date': time.strftime("%Y-%m-%d"), + 'step1': '1', + 'status_id': status_id, + 'uploaded_notes': '', + 'uploaded_changes': '', + 'release_notes': release_notes, + 'release_changes': change_log, + 'preformatted': '1', + 'submit': 'Submit/Refresh' + } + + try: + ok = self.fetch_url(url, + urlencode(form), + ok_status="Data Saved", + retry=False)[1] + except: + ok = False + + return ok + def edit_release_step2(self, group_id, package_id, release_id, fileVOs): url = EDIT_RELEASE_URL @@ -421,7 +525,7 @@ error("Error selecting %s for inclusion", filename) #debug("dumping data: %s", data) # remove me... ok = False - + matches = GET_FILE_ID.findall(data) lookup = {} for match in matches: @@ -432,7 +536,7 @@ def edit_release_step3(self, group_id, package_id, release_id, fileVOs, lookup_dict): url = EDIT_RELEASE_URL - + form = {'package_id': package_id, 'group_id': group_id, 'release_id': release_id, @@ -446,8 +550,10 @@ form['processor_id'] = fileVO.getProcessorId() form['type_id'] = fileVO.getFileTypeId() try: - #debug("filename: %s", fileVO.getFilename() ) - #debug("dict: %s", str(lookup_dict)) + # REMOVE THESE!!!!! for debugging purpose re: twb + #error("filename: %s", fileVO.getFilename() ) + #error("dict: %s", str(lookup_dict)) + ###### form['file_id'] = lookup_dict[fileVO.getFilename()] ok &= self.fetch_url(url, urlencode(form), ok_status="File Updated")[1] @@ -510,29 +616,23 @@ status) - def upload_files(self, parent, fileVOs): - ftp = FTP_() + def upload_files(self, parent, fileVOs): try: - ftp.connect(SF_FTP_SERVER) - ftp.getwelcome() - - ftp.login("ftp", "releaseforge") - ftp.cwd(SF_FTP_DIRECTORY) + t = paramiko.Transport((SF_SFTP_SERVER, SF_SFTP_PORT)) + t.start_client() + t.auth_password(self.username, self.password) + sftp = paramiko.SFTPClient.from_transport(t) + sftp.chdir(SF_SFTP_DIRECTORY) + num_uploaded = 0 - for fileVO in fileVOs: fullpath = fileVO.getFullPath() filename = fileVO.getFilename() debug("uploading %s (%s)", filename, fullpath) progressMessageQueue.put("Uploading: %s" % filename) - f = open(fullpath, "rb") - - ftp.storbinary('STOR ' + filename, - f, - callback=self.update_ftp_progress) - f.close() + sftp.put(fullpath, filename, callback=self.update_sftp_progress) num_uploaded += 1 if parent.isCancelled(): break @@ -542,21 +642,22 @@ msg = "Successfully uploaded %d files" % num_uploaded except Exception, e: msg = str(e) - progressMessageQueue.put("FTP error: %s" % msg) + error(msg) + progressMessageQueue.put("SFTP error: %s" % msg) debug(msg) try: - ftp.close() + sftp.close() except: pass - ftpProgressQueue.clear() - ftpProgressQueue.put( (True, True) ) + sftpProgressQueue.clear() + sftpProgressQueue.put( (True, True) ) return msg - def update_ftp_progress(self, progress): + def update_sftp_progress(self, progress, total): #debug("progress: %s", progress) - ftpProgressQueue.clear() - ftpProgressQueue.put(progress) + sftpProgressQueue.clear() + sftpProgressQueue.put( (progress, total) ) def submit_news(self, group_id, subject, message): diff -Nru /tmp/user/2000/X5m6gbvF7f/releaseforge-1.1/ReleaseForge/version.py /tmp/user/2000/EZty4Ck08i/releaseforge-1.3/ReleaseForge/version.py --- releaseforge-1.1/ReleaseForge/version.py 2006-06-15 06:01:54.000000000 -0400 +++ releaseforge-1.3/ReleaseForge/version.py 2008-07-07 12:17:32.000000000 -0400 @@ -1 +1 @@ -VERSION="1.1" +VERSION="1.3" diff -Nru /tmp/user/2000/X5m6gbvF7f/releaseforge-1.1/debian/changelog /tmp/user/2000/EZty4Ck08i/releaseforge-1.3/debian/changelog --- releaseforge-1.1/debian/changelog 2008-08-02 13:50:52.000000000 -0400 +++ releaseforge-1.3/debian/changelog 2008-08-02 13:50:53.000000000 -0400 @@ -1,3 +1,14 @@ +releaseforge (1.3-1) unstable; urgency=low + + * New upstream release. (Closes: #492933) + - Remove patches now included upstream: + + debian/patches/02_empty_set.dpatch + + debian/patches/03_new_login_form.dpatch + - Add dependency on python-paramiko (>= 1.7.4) + * Updated Standards-Version to 3.8.0 (no changes) + + -- Roberto C. Sanchez <[EMAIL PROTECTED]> Fri, 01 Aug 2008 23:53:10 -0400 + releaseforge (1.1-4) unstable; urgency=low * Update man page. diff -Nru /tmp/user/2000/X5m6gbvF7f/releaseforge-1.1/debian/control /tmp/user/2000/EZty4Ck08i/releaseforge-1.3/debian/control --- releaseforge-1.1/debian/control 2008-08-02 13:50:52.000000000 -0400 +++ releaseforge-1.3/debian/control 2008-08-02 13:50:53.000000000 -0400 @@ -5,11 +5,11 @@ Homepage: http://releaseforge.sourceforge.net/ Build-Depends: debhelper (>= 5.0.37.2), dpatch Build-Depends-Indep: python, python-dev, python-qt3 (>= 3.13), pyqt-tools (>= 3.14.1), python-support (>= 0.5.6) -Standards-Version: 3.7.3 +Standards-Version: 3.8.0 Package: releaseforge Architecture: all -Depends: ${python:Depends}, python-qt3 (>= 3.13) +Depends: ${python:Depends}, python-qt3 (>= 3.13), python-paramiko (>= 1.7.4) Description: alternative to SourceForge's File Release System (FRS) An open source utility designed for the administrators and release engineers of SourceForge projects. ReleaseForge allows diff -Nru /tmp/user/2000/X5m6gbvF7f/releaseforge-1.1/debian/copyright /tmp/user/2000/EZty4Ck08i/releaseforge-1.3/debian/copyright --- releaseforge-1.1/debian/copyright 2008-08-02 13:50:52.000000000 -0400 +++ releaseforge-1.3/debian/copyright 2008-08-02 13:50:53.000000000 -0400 @@ -3,7 +3,9 @@ It was downloaded from http://releaseforge.sourceforge.net/ -Copyright Holder: Copyright (c) 2005 Phil Schwartz <[EMAIL PROTECTED]> +Copyright Holder: + +Copyright (c) 2005 Phil Schwartz <[EMAIL PROTECTED]> License: diff -Nru /tmp/user/2000/X5m6gbvF7f/releaseforge-1.1/debian/patches/00list /tmp/user/2000/EZty4Ck08i/releaseforge-1.3/debian/patches/00list --- releaseforge-1.1/debian/patches/00list 2008-08-02 13:50:52.000000000 -0400 +++ releaseforge-1.3/debian/patches/00list 2008-08-02 13:50:53.000000000 -0400 @@ -1,3 +1 @@ 01_interpreter_patch.dpatch -02_empty_set.dpatch -03_new_login_form.dpatch diff -Nru /tmp/user/2000/X5m6gbvF7f/releaseforge-1.1/debian/patches/02_empty_set.dpatch /tmp/user/2000/EZty4Ck08i/releaseforge-1.3/debian/patches/02_empty_set.dpatch --- releaseforge-1.1/debian/patches/02_empty_set.dpatch 2008-08-02 13:50:52.000000000 -0400 +++ releaseforge-1.3/debian/patches/02_empty_set.dpatch 1969-12-31 19:00:00.000000000 -0500 @@ -1,25 +0,0 @@ -#! /bin/sh /usr/share/dpatch/dpatch-run -## 02_empty_set.dpatch by <[EMAIL PROTECTED]> -## -## All lines beginning with `## DP:' are a description of the patch. -## DP: Fixes return of non-existent variable - [EMAIL PROTECTED]@ - -diff -uNr releaseforge-1.1.orig/ReleaseForge/sfcomm.py releaseforge-1.1/ReleaseForge/sfcomm.py ---- releaseforge-1.1.orig/ReleaseForge/sfcomm.py 2006-06-15 05:49:44.000000000 -0400 -+++ releaseforge-1.1/ReleaseForge/sfcomm.py 2006-08-03 18:28:07.099087126 -0400 -@@ -169,12 +169,12 @@ - cj.save(self.cookie_file, True, True) # ignore discard! ignore expires - - data = r.read() -+ projects = set() - idx = data.find("Invalid Password or User Name") - if idx != -1: - debug("Could not login") - return projects - -- projects = set() - #debug(data) - project_tuples = PROJECTS_FROM_MY_PROJECTS.findall(data) - for pt in project_tuples: diff -Nru /tmp/user/2000/X5m6gbvF7f/releaseforge-1.1/debian/patches/03_new_login_form.dpatch /tmp/user/2000/EZty4Ck08i/releaseforge-1.3/debian/patches/03_new_login_form.dpatch --- releaseforge-1.1/debian/patches/03_new_login_form.dpatch 2008-08-02 13:50:52.000000000 -0400 +++ releaseforge-1.3/debian/patches/03_new_login_form.dpatch 1969-12-31 19:00:00.000000000 -0500 @@ -1,24 +0,0 @@ -#! /bin/sh /usr/share/dpatch/dpatch-run -## 03_new_login_form.dpatch by <[EMAIL PROTECTED]> -## -## All lines beginning with `## DP:' are a description of the patch. -## DP: New login form - [EMAIL PROTECTED]@ - -Index: trunk/ReleaseForge/sfcomm.py -=================================================================== ---- trunk/ReleaseForge/sfcomm.py (revision 761) -+++ trunk/ReleaseForge/sfcomm.py (working copy) -@@ -143,9 +143,8 @@ - debug("Attempting to login to SourceForge") - form = {'form_loginname': username, - 'form_pw': password, -- 'stay_in_ssl': '1', -- 'persistent_login': '1', -- 'login': 'Login With SSL'} -+ 'ssl_status': '1', -+ 'login': 'Login+in'} - url = LOGIN_URL - - if return_to: url += "?return_to=%s" % quote_plus(return_to) diff -Nru /tmp/user/2000/X5m6gbvF7f/releaseforge-1.1/setup.cfg /tmp/user/2000/EZty4Ck08i/releaseforge-1.3/setup.cfg --- releaseforge-1.1/setup.cfg 2006-06-15 06:01:18.000000000 -0400 +++ releaseforge-1.3/setup.cfg 2008-06-22 21:08:50.000000000 -0400 @@ -5,7 +5,10 @@ distribution-name = Red Hat Linux requires = python >= 2.3 requires = PyQt >= 3.2 +requires = paramiko > 1.7.3 build-requires = python-devel -doc_files = README.txt LICENSE.txt CHANGELOG.txt +#doc_files = README.txt LICENSE.txt CHANGELOG.txt #icon = images/releaseforge-icon.png install-script = install.sh +[install] +optimize = 1 diff -Nru /tmp/user/2000/X5m6gbvF7f/releaseforge-1.1/setup.py /tmp/user/2000/EZty4Ck08i/releaseforge-1.3/setup.py --- releaseforge-1.1/setup.py 2006-03-31 23:21:15.000000000 -0500 +++ releaseforge-1.3/setup.py 2008-07-07 12:17:08.000000000 -0400 @@ -1,6 +1,7 @@ #!/usr/bin/env python from ReleaseForge.version import VERSION from distutils.core import setup +#from setuptools import setup import os import os.path import sys @@ -43,6 +44,7 @@ (libpath, glob('releaseforge.pro')), (libpath, glob('logger.ini')), (libpath, glob('README.txt')), + (libpath, glob('RELEASE_NOTES.txt')), (libpath, glob('CHANGELOG.txt')), (libpath, glob('LICENSE.txt')), # (TRANSLATIONS_DIR, glob(os.path.join("translations", "*"))),
signature.asc
Description: Digital signature