Changeset - 2a8bf2a3da98
[Not reviewed]
beta
0 2 0
Marcin Kuzminski - 14 years ago 2011-08-26 23:59:12
marcin@python-works.com
fixes #214 added support for downloading subrepos in download menu.
2 files changed with 21 insertions and 16 deletions:
0 comments (0 inline, 0 general)
rhodecode/controllers/files.py
Show inline comments
 
@@ -178,222 +178,223 @@ class FilesController(BaseRepoController
 
            'image/svg+xml': ('image/svg+xml', 'inline'),
 
        }
 

	
 
        mimetype = file_node.mimetype
 
        try:
 
            mimetype, dispo = raw_mimetype_mapping[mimetype]
 
        except KeyError:
 
            # we don't know anything special about this, handle it safely
 
            if file_node.is_binary:
 
                # do same as download raw for binary files
 
                mimetype, dispo = 'application/octet-stream', 'attachment'
 
            else:
 
                # do not just use the original mimetype, but force text/plain,
 
                # otherwise it would serve text/html and that might be unsafe.
 
                # Note: underlying vcs library fakes text/plain mimetype if the
 
                # mimetype can not be determined and it thinks it is not
 
                # binary.This might lead to erroneous text display in some
 
                # cases, but helps in other cases, like with text files
 
                # without extension.
 
                mimetype, dispo = 'text/plain', 'inline'
 

	
 
        if dispo == 'attachment':
 
            dispo = 'attachment; filename=%s' % \
 
                        safe_str(f_path.split(os.sep)[-1])
 

	
 
        response.content_disposition = dispo
 
        response.content_type = mimetype
 
        return file_node.content
 

	
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def annotate(self, repo_name, revision, f_path):
 
        c.cs = self.__get_cs_or_redirect(revision, repo_name)
 
        c.file = self.__get_filenode_or_redirect(repo_name, c.cs, f_path)
 

	
 
        c.file_history = self._get_node_history(c.cs, f_path)
 
        c.f_path = f_path
 
        return render('files/files_annotate.html')
 

	
 
    @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
 
    def edit(self, repo_name, revision, f_path):
 
        r_post = request.POST
 

	
 
        c.cs = self.__get_cs_or_redirect(revision, repo_name)
 
        c.file = self.__get_filenode_or_redirect(repo_name, c.cs, f_path)
 

	
 
        if c.file.is_binary:
 
            return redirect(url('files_home', repo_name=c.repo_name,
 
                         revision=c.cs.raw_id, f_path=f_path))
 

	
 
        c.file_history = self._get_node_history(c.cs, f_path)
 
        c.f_path = f_path
 

	
 
        if r_post:
 

	
 
            old_content = c.file.content
 
            sl = old_content.splitlines(1)
 
            first_line = sl[0] if sl else ''
 
            # modes:  0 - Unix, 1 - Mac, 2 - DOS
 
            mode = detect_mode(first_line, 0)
 
            content = convert_line_endings(r_post.get('content'), mode)
 

	
 
            message = r_post.get('message') or (_('Edited %s via RhodeCode')
 
                                                % (f_path))
 
            author = self.rhodecode_user.full_contact
 

	
 
            if content == old_content:
 
                h.flash(_('No changes'),
 
                    category='warning')
 
                return redirect(url('changeset_home', repo_name=c.repo_name,
 
                                    revision='tip'))
 

	
 
            try:
 
                self.scm_model.commit_change(repo=c.rhodecode_repo,
 
                                             repo_name=repo_name, cs=c.cs,
 
                                             user=self.rhodecode_user,
 
                                             author=author, message=message,
 
                                             content=content, f_path=f_path)
 
                h.flash(_('Successfully committed to %s' % f_path),
 
                        category='success')
 

	
 
            except Exception:
 
                log.error(traceback.format_exc())
 
                h.flash(_('Error occurred during commit'), category='error')
 
            return redirect(url('changeset_home',
 
                                repo_name=c.repo_name, revision='tip'))
 

	
 
        return render('files/files_edit.html')
 

	
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def archivefile(self, repo_name, fname):
 

	
 
        fileformat = None
 
        revision = None
 
        ext = None
 
        subrepos = request.GET.get('subrepos') == 'true'
 

	
 
        for a_type, ext_data in ARCHIVE_SPECS.items():
 
            archive_spec = fname.split(ext_data[1])
 
            if len(archive_spec) == 2 and archive_spec[1] == '':
 
                fileformat = a_type or ext_data[1]
 
                revision = archive_spec[0]
 
                ext = ext_data[1]
 

	
 
        try:
 
            dbrepo = RepoModel().get_by_repo_name(repo_name)
 
            if dbrepo.enable_downloads is False:
 
                return _('downloads disabled')
 

	
 
            cs = c.rhodecode_repo.get_changeset(revision)
 
            content_type = ARCHIVE_SPECS[fileformat][0]
 
        except ChangesetDoesNotExistError:
 
            return _('Unknown revision %s') % revision
 
        except EmptyRepositoryError:
 
            return _('Empty repository')
 
        except (ImproperArchiveTypeError, KeyError):
 
            return _('Unknown archive type')
 

	
 
        response.content_type = content_type
 
        response.content_disposition = 'attachment; filename=%s-%s%s' \
 
            % (repo_name, revision, ext)
 

	
 
        import tempfile
 
        archive = tempfile.mkstemp()[1]
 
        t = open(archive, 'wb')
 
        cs.fill_archive(stream=t, kind=fileformat)
 
        cs.fill_archive(stream=t, kind=fileformat, subrepos=subrepos)
 

	
 
        def get_chunked_archive(archive):
 
            stream = open(archive, 'rb')
 
            while True:
 
                data = stream.read(4096)
 
                if not data:
 
                    os.remove(archive)
 
                    break
 
                yield data
 

	
 
        return get_chunked_archive(archive)
 

	
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def diff(self, repo_name, f_path):
 
        diff1 = request.GET.get('diff1')
 
        diff2 = request.GET.get('diff2')
 
        c.action = request.GET.get('diff')
 
        c.no_changes = diff1 == diff2
 
        c.f_path = f_path
 
        c.big_diff = False
 

	
 
        try:
 
            if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
 
                c.changeset_1 = c.rhodecode_repo.get_changeset(diff1)
 
                node1 = c.changeset_1.get_node(f_path)
 
            else:
 
                c.changeset_1 = EmptyChangeset(repo=c.rhodecode_repo)
 
                node1 = FileNode('.', '', changeset=c.changeset_1)
 

	
 
            if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]:
 
                c.changeset_2 = c.rhodecode_repo.get_changeset(diff2)
 
                node2 = c.changeset_2.get_node(f_path)
 
            else:
 
                c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo)
 
                node2 = FileNode('.', '', changeset=c.changeset_2)
 
        except RepositoryError:
 
            return redirect(url('files_home',
 
                                repo_name=c.repo_name, f_path=f_path))
 

	
 
        if c.action == 'download':
 
            diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
 
                                        format='gitdiff')
 

	
 
            diff_name = '%s_vs_%s.diff' % (diff1, diff2)
 
            response.content_type = 'text/plain'
 
            response.content_disposition = 'attachment; filename=%s' \
 
                                                    % diff_name
 
            return diff.raw_diff()
 

	
 
        elif c.action == 'raw':
 
            diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
 
                                        format='gitdiff')
 
            response.content_type = 'text/plain'
 
            return diff.raw_diff()
 

	
 
        elif c.action == 'diff':
 
            if node1.is_binary or node2.is_binary:
 
                c.cur_diff = _('Binary file')
 
            elif node1.size > self.cut_off_limit or \
 
                    node2.size > self.cut_off_limit:
 
                c.cur_diff = ''
 
                c.big_diff = True
 
            else:
 
                diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
 
                                        format='gitdiff')
 
                c.cur_diff = diff.as_html()
 
        else:
 

	
 
            #default option
 
            if node1.is_binary or node2.is_binary:
 
                c.cur_diff = _('Binary file')
 
            elif node1.size > self.cut_off_limit or \
 
                    node2.size > self.cut_off_limit:
 
                c.cur_diff = ''
 
                c.big_diff = True
 

	
 
            else:
 
                diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
 
                                        format='gitdiff')
 
                c.cur_diff = diff.as_html()
 

	
 
        if not c.cur_diff and not c.big_diff:
 
            c.no_changes = True
 
        return render('files/file_diff.html')
 

	
 
    def _get_node_history(self, cs, f_path):
 
        changesets = cs.get_file_history(f_path)
 
        hist_l = []
 

	
 
        changesets_group = ([], _("Changesets"))
 
        branches_group = ([], _("Branches"))
 
        tags_group = ([], _("Tags"))
 

	
 
        for chs in changesets:
 
            n_desc = 'r%s:%s' % (chs.revision, chs.short_id)
rhodecode/templates/summary/summary.html
Show inline comments
 
@@ -71,327 +71,331 @@
 
	            	${_('Fork of')} ${c.dbrepo.fork.repo_name}
 
	            	</a>
 
	            	</div>
 
		          %endif
 
		          ##REMOTE
 
				  %if c.dbrepo.clone_uri:
 
                    <div style="margin-top:5px;clear:both">
 
                    <a href="${h.url(str(h.hide_credentials(c.dbrepo.clone_uri)))}">
 
                    <img class="icon" alt="${_('remote clone')}"
 
                    title="${_('Clone from')} ${h.hide_credentials(c.dbrepo.clone_uri)}" 
 
                    src="${h.url("/images/icons/connect.png")}"/>
 
                    ${_('Clone from')} ${h.hide_credentials(c.dbrepo.clone_uri)}
 
                    </a>
 
                    </div>					
 
				  %endif		            		      
 
			  </div>
 
			 </div>
 
			
 
			
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Description')}:</label>
 
			  </div>
 
			  <div class="input-short desc">${h.urlify_text(c.dbrepo.description)}</div>
 
			 </div>
 
			
 
			
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Contact')}:</label>
 
			  </div>
 
			  <div class="input-short">
 
			  	<div class="gravatar">
 
			  		<img alt="gravatar" src="${h.gravatar_url(c.dbrepo.user.email)}"/>
 
			  	</div>
 
			  		${_('Username')}: ${c.dbrepo.user.username}<br/>
 
			  		${_('Name')}: ${c.dbrepo.user.name} ${c.dbrepo.user.lastname}<br/>
 
			  		${_('Email')}: <a href="mailto:${c.dbrepo.user.email}">${c.dbrepo.user.email}</a>
 
			  </div>
 
			 </div>
 
			
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Last change')}:</label>
 
			  </div>
 
			  <div class="input-short">
 
                  <b>${'r%s:%s' % (h.get_changeset_safe(c.rhodecode_repo,'tip').revision,
 
                            h.get_changeset_safe(c.rhodecode_repo,'tip').short_id)}</b> - 
 
			      <span class="tooltip" title="${c.rhodecode_repo.last_change}">
 
			      ${h.age(c.rhodecode_repo.last_change)}</span><br/>
 
			      ${_('by')} ${h.get_changeset_safe(c.rhodecode_repo,'tip').author} 
 
			      
 
			  </div>
 
			 </div>
 
			
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Clone url')}:</label>
 
			  </div>
 
			  <div class="input-short">
 
			      <input type="text" id="clone_url" readonly="readonly" value="${c.rhodecode_repo.alias} clone ${c.clone_repo_url}" size="70"/>
 
			  </div>
 
			 </div>
 
			 
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Trending source files')}:</label>
 
			  </div>
 
			  <div class="input-short">
 
			    <div id="lang_stats"></div> 			   
 
			  </div>
 
			 </div>
 
			 			
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Download')}:</label>
 
			  </div>
 
			  <div class="input-short">
 
		        %if len(c.rhodecode_repo.revisions) == 0:
 
		          ${_('There are no downloads yet')}
 
		        %elif c.enable_downloads is False:
 
		          ${_('Downloads are disabled for this repository')}
 
                    %if h.HasPermissionAll('hg.admin')('enable stats on from summary'):
 
                        [${h.link_to(_('enable'),h.url('edit_repo',repo_name=c.repo_name))}]
 
                    %endif  		          
 
		        %else:
 
			        ${h.select('download_options',c.rhodecode_repo.get_changeset().raw_id,c.download_options)}
 
			        %for cnt,archive in enumerate(c.rhodecode_repo._get_archives()):
 
			             %if cnt >=1:
 
			             |
 
			             %endif
 
			             <span class="tooltip" title="${_('Download %s as %s') %('tip',archive['type'])}" 
 
			                  id="${archive['type']+'_link'}">${h.link_to(archive['type'],
 
			                h.url('files_archive_home',repo_name=c.dbrepo.repo_name,
 
			                fname='tip'+archive['extension']),class_="archive_icon")}</span>
 
			        %endfor
 
                    <span style="vertical-align: bottom">
 
                        <input id="archive_subrepos" type="checkbox" name="subrepos"/> <span class="tooltip" title="${_('Check this to download archive with subrepos')}" >${_('with subrepos')}</span>
 
                    </span>
 
			    %endif
 
			  </div>
 
			 </div>
 
			 
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Feeds')}:</label>
 
			  </div>
 
			  <div class="input-short">
 
			   %if c.rhodecode_user.username != 'default':
 
	            ${h.link_to(_('RSS'),h.url('rss_feed_home',repo_name=c.dbrepo.repo_name,api_key=c.rhodecode_user.api_key),class_='rss_icon')}
 
	            ${h.link_to(_('Atom'),h.url('atom_feed_home',repo_name=c.dbrepo.repo_name,api_key=c.rhodecode_user.api_key),class_='atom_icon')}
 
	           %else:
 
                ${h.link_to(_('RSS'),h.url('rss_feed_home',repo_name=c.dbrepo.repo_name),class_='rss_icon')}
 
                ${h.link_to(_('Atom'),h.url('atom_feed_home',repo_name=c.dbrepo.repo_name),class_='atom_icon')}	           
 
	           %endif 
 
			  </div>
 
			 </div>				 			 			 
 
	  </div>		 
 
	</div>
 
  	<script type="text/javascript">
 
	  	YUE.onDOMReady(function(e){
 
	  	    id = 'clone_url';
 
	  	    YUE.on(id,'click',function(e){
 
	  	    	if(YUD.hasClass(id,'selected')){
 
	  	    		return
 
	  	    	}
 
	  	    	else{
 
	                YUD.addClass(id,'selected');
 
	                YUD.get(id).select();	  	    		
 
	  	    	}
 

	
 
	  	    })
 
	  	})
 
  		var data = ${c.trending_languages|n};
 
  		var total = 0;
 
  		var no_data = true;
 
  		for (k in data){
 
  		    total += data[k].count;
 
  		    no_data = false;
 
  		} 
 
		var tbl = document.createElement('table');
 
		tbl.setAttribute('class','trending_language_tbl');
 
		var cnt = 0;
 
  		for (k in data){
 
  			cnt += 1;
 
  			var hide = cnt>2;
 
	  		var tr = document.createElement('tr');
 
	  		if (hide){
 
	  			tr.setAttribute('style','display:none');
 
	  			tr.setAttribute('class','stats_hidden');
 
	  		}
 
	  		var percentage = Math.round((data[k].count/total*100),2);
 
			var value = data[k].count;
 
	  		var td1 = document.createElement('td');
 
	  		td1.width = 150;
 
	  		var trending_language_label = document.createElement('div');
 
	  		trending_language_label.innerHTML = data[k].desc+" ("+k+")";
 
	  		td1.appendChild(trending_language_label);
 

	
 
	  		var td2 = document.createElement('td');
 
	  		td2.setAttribute('style','padding-right:14px !important');
 
  		    var trending_language = document.createElement('div');
 
  		    var nr_files = value+" ${_('files')}";
 
  		    
 
  		    trending_language.title = k+" "+nr_files;
 
  		    
 
  		    if (percentage>22){
 
  		    	trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"% "+nr_files+ "</b>";	
 
  		    }
 
  		    else{
 
  		    	trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"%</b>";
 
  		    }
 
  		    
 
  		    trending_language.setAttribute("class", 'trending_language top-right-rounded-corner bottom-right-rounded-corner');
 
  		    trending_language.style.width=percentage+"%";
 
			td2.appendChild(trending_language);
 
			
 
			tr.appendChild(td1);
 
			tr.appendChild(td2);
 
  		    tbl.appendChild(tr);
 
  		    if(cnt == 3){
 
  		    	var show_more = document.createElement('tr');
 
  		    	var td = document.createElement('td');
 
  		    	lnk = document.createElement('a');
 
  		    	
 
  		    	lnk.href='#';
 
  		    	lnk.innerHTML = "${_('show more')}";
 
  		    	lnk.id='code_stats_show_more';
 
  		        td.appendChild(lnk);
 
  		        
 
  		    	show_more.appendChild(td);
 
  		    	show_more.appendChild(document.createElement('td'));
 
  		    	tbl.appendChild(show_more);
 
  		    }
 
  		    
 
  		}
 
  		if(no_data){
 
  			var tr = document.createElement('tr');
 
  			var td1 = document.createElement('td');
 
  			td1.innerHTML = "${c.no_data_msg}";
 
  			tr.appendChild(td1);
 
  			tbl.appendChild(tr);
 
		}
 
  		YUD.get('lang_stats').appendChild(tbl);
 
  		YUE.on('code_stats_show_more','click',function(){
 
  			l = YUD.getElementsByClassName('stats_hidden')
 
  			for (e in l){
 
  			    YUD.setStyle(l[e],'display','');
 
  			};
 
  			YUD.setStyle(YUD.get('code_stats_show_more'),
 
  					'display','none');
 
  		})
 
  	
 
             
 
             YUE.on('download_options','change',function(e){
 
                 var new_cs = e.target.options[e.target.selectedIndex];
 
                 var tmpl_links = {}
 
                 %for cnt,archive in enumerate(c.rhodecode_repo._get_archives()):
 
                	 tmpl_links['${archive['type']}'] = '${h.link_to(archive['type'],
 
                        h.url('files_archive_home',repo_name=c.dbrepo.repo_name,
 
                        fname='__CS__'+archive['extension']),class_="archive_icon")}';
 
                 %endfor
 
                
 
             var tmpl_links = {}
 
              %for cnt,archive in enumerate(c.rhodecode_repo._get_archives()):
 
                tmpl_links['${archive['type']}'] = '${h.link_to(archive['type'],
 
                     h.url('files_archive_home',repo_name=c.dbrepo.repo_name,
 
                     fname='__CS__'+archive['extension'],subrepos='__SUB__'),class_="archive_icon")}';
 
              %endfor
 
              
 
             YUE.on(['download_options','archive_subrepos'],'change',function(e){
 
            	 var sm = YUD.get('download_options');
 
                 var new_cs = sm.options[sm.selectedIndex];
 
                 
 
                 for(k in tmpl_links){
 
                	 var s = YUD.get(k+'_link')
 
                	 var s = YUD.get(k+'_link');
 
                	 title_tmpl = "${_('Download %s as %s') % ('__CS_NAME__','__CS_EXT__')}";
 
                	 s.title = title_tmpl.replace('__CS_NAME__',new_cs.text);
 
                	 s.title = s.title.replace('__CS_EXT__',k);
 
                	 s.innerHTML = tmpl_links[k].replace('__CS__',new_cs.value);
 
                	 var url = tmpl_links[k].replace('__CS__',new_cs.value);
 
                	 var subrepos = YUD.get('archive_subrepos').checked
 
                	 url = url.replace('__SUB__',subrepos);
 
                	 s.innerHTML = url 
 
                 }
 
                 
 
             })
 
             	
 
             });
 
  	</script>    				
 
</div>
 
        
 
<div class="box box-right"  style="min-height:455px">
 
    <!-- box / title -->
 
    <div class="title">
 
        <h5>${_('Commit activity by day / author')}</h5>
 
    </div>
 
    
 
    <div class="graph">
 
         <div style="padding:0 10px 10px 15px;font-size: 1.2em;">
 
         %if c.no_data:
 
           ${c.no_data_msg}
 
           %if h.HasPermissionAll('hg.admin')('enable stats on from summary'):
 
                [${h.link_to(_('enable'),h.url('edit_repo',repo_name=c.repo_name))}]
 
           %endif         
 
           
 
        %else:
 
            ${_('Loaded in')} ${c.stats_percentage} %
 
        %endif
 
        </div>  
 
        <div id="commit_history" style="width:450px;height:300px;float:left"></div>
 
        <div style="clear: both;height: 10px"></div>
 
        <div id="overview" style="width:450px;height:100px;float:left"></div>
 
        
 
    	<div id="legend_data" style="clear:both;margin-top:10px;">
 
	    	<div id="legend_container"></div>
 
	    	<div id="legend_choices">
 
				<table id="legend_choices_tables" style="font-size:smaller;color:#545454"></table>
 
	    	</div>
 
    	</div>
 
		<script type="text/javascript">
 
		/**
 
		 * Plots summary graph
 
		 *
 
		 * @class SummaryPlot
 
		 * @param {from} initial from for detailed graph
 
		 * @param {to} initial to for detailed graph
 
		 * @param {dataset}
 
		 * @param {overview_dataset}
 
		 */
 
		function SummaryPlot(from,to,dataset,overview_dataset) {
 
			var initial_ranges = {
 
			    "xaxis":{
 
				    "from":from,
 
				   	"to":to,
 
				},
 
			};
 
		    var dataset = dataset;
 
		    var overview_dataset = [overview_dataset];
 
		    var choiceContainer = YUD.get("legend_choices");
 
		    var choiceContainerTable = YUD.get("legend_choices_tables");
 
		    var plotContainer = YUD.get('commit_history');
 
		    var overviewContainer = YUD.get('overview');
 
		    
 
		    var plot_options = {
 
				bars: {show:true,align:'center',lineWidth:4},
 
				legend: {show:true, container:"legend_container"},
 
				points: {show:true,radius:0,fill:false},
 
				yaxis: {tickDecimals:0,},
 
				xaxis: {
 
					mode: "time", 
 
					timeformat: "%d/%m",
 
				    min:from,
 
				    max:to,	
 
				}, 
 
				grid: {
 
					hoverable: true, 
 
				    clickable: true,
 
				    autoHighlight:true,
 
				    color: "#999"
 
				},
 
				//selection: {mode: "x"}
 
		    };
 
		    var overview_options = {
 
				legend:{show:false},
 
			    bars: {show:true,barWidth: 2,},
 
			    shadowSize: 0,
 
			    xaxis: {mode: "time", timeformat: "%d/%m/%y",},
 
			    yaxis: {ticks: 3, min: 0,tickDecimals:0,},
 
			    grid: {color: "#999",},
 
			    selection: {mode: "x"}
 
			};
 

	
 
			/**
 
			*get dummy data needed in few places
 
			*/
 
		    function getDummyData(label){
 
		    	return {"label":label,
 
               	 "data":[{"time":0,
 
               		 "commits":0,
 
	                     "added":0,
 
	                     "changed":0,
 
	                     "removed":0,
 
                    }],
 
                    "schema":["commits"],
0 comments (0 inline, 0 general)